Commit ed9ad59672c for nodejs

commit ed9ad59672c447727725d97ed98f87e4d525f8c4
Author: agape1225 <49804691+agape1225@users.noreply.github.com>
Date:   Tue Sep 22 22:27:47 2026 +0900

    util: show SuppressedError's error/suppressed properties on inspect

    util.inspect() (and console.log()) silently dropped a SuppressedError's
    `error` and `suppressed` properties, the two pieces of information
    needed to actually debug a disposal failure. Both properties are
    non-enumerable, so they never showed up without this.

    formatError() already special-cases two other non-enumerable
    "container" properties for the same reason: Error's `cause` (#41002)
    and AggregateError's `errors` (#43646). Handle SuppressedError's
    `error` and `suppressed` the same way; nested SuppressedErrors (from
    multiple failed disposals) are shown recursively since inspect()
    already recurses into any Error-valued property.

    Fixes: https://github.com/nodejs/node/issues/66033

    Signed-off-by: agape1225 <49804691+agape1225@users.noreply.github.com>
    PR-URL: https://github.com/nodejs/node/pull/66159
    Fixes: https://github.com/nodejs/node/issues/66033
    Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
    Reviewed-By: James M Snell <jasnell@gmail.com>
    Reviewed-By: Jordan Harband <ljharb@gmail.com>

diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js
index 2e6c564cd3c..cf0a8892f8f 100644
--- a/lib/internal/util/inspect.js
+++ b/lib/internal/util/inspect.js
@@ -1990,6 +1990,16 @@ function formatError(err, constructor, tag, ctx, keys) {
     // If errors is a getter that throws, we ignore the error.
   }

+  // Print the wrapped errors of a SuppressedError.
+  if (ObjectPrototypeHasOwnProperty(err, 'error') &&
+      (keys.length === 0 || !ArrayPrototypeIncludes(keys, 'error'))) {
+    ArrayPrototypePush(keys, 'error');
+  }
+  if (ObjectPrototypeHasOwnProperty(err, 'suppressed') &&
+      (keys.length === 0 || !ArrayPrototypeIncludes(keys, 'suppressed'))) {
+    ArrayPrototypePush(keys, 'suppressed');
+  }
+
   stack = improveStack(stack, constructor, name, tag);

   // Ignore the error message if it's contained in the stack.
diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js
index ae5289cc721..c85ee620d63 100644
--- a/test/parallel/test-util-inspect.js
+++ b/test/parallel/test-util-inspect.js
@@ -735,6 +735,53 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324');
   Error.stackTraceLimit = stackTraceLimit;
 }

+{
+  // The `error` and `suppressed` properties of a SuppressedError should be
+  // shown during inspection, same as `cause` and AggregateError's `errors`.
+  const { stackTraceLimit } = Error;
+  Error.stackTraceLimit = 0;
+
+  const disposeError = new Error('dispose error');
+  const bodyError = new Error('body error');
+  const suppressedError = new SuppressedError(
+    disposeError,
+    bodyError,
+    'An error was suppressed during disposal',
+  );
+
+  assert.strictEqual(
+    util.inspect(suppressedError),
+    '[SuppressedError: An error was suppressed during disposal] ' +
+    '{\n  [error]: [Error: dispose error],\n  [suppressed]: [Error: body error]\n}',
+  );
+
+  // Nested SuppressedErrors (multiple failed disposals) must recurse.
+  const outer = new SuppressedError(
+    new Error('second dispose error'),
+    suppressedError,
+    'outer',
+  );
+  assert.strictEqual(
+    util.inspect(outer),
+    '[SuppressedError: outer] {\n' +
+    '  [error]: [Error: second dispose error],\n' +
+    '  [suppressed]: [SuppressedError: An error was suppressed during disposal] {\n' +
+    '    [error]: [Error: dispose error],\n' +
+    '    [suppressed]: [Error: body error]\n' +
+    '  }\n' +
+    '}',
+  );
+
+  const custom = new Error('No own error/suppressed property');
+  Object.setPrototypeOf(custom, suppressedError);
+  assert.strictEqual(
+    util.inspect(custom),
+    '[SuppressedError: No own error/suppressed property]',
+  );
+
+  Error.stackTraceLimit = stackTraceLimit;
+}
+
 {
   const tmp = Error.stackTraceLimit;
   // Force stackTraceLimit = 0 for this test, but make it non-enumerable