util: `SuppressedError` should print `error`/`suppressed` properties during inspection
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 122k
- Forks
- 37.3k
- Avg merge
- 4d 2h
- Merged PRs (30d)
- 283
Description
What is the problem this feature will solve?
When a SuppressedError is thrown (e.g. from disposal errors during a using/await using block) and inspected via util.inspect() / console.log(), then the actual underlying errors (error and suppressed properties) are not shown:
class Resource {
[Symbol.dispose]() {
throw new Error('error during dispose');
}
}
function test() {
using res = new Resource();
throw new Error('error during execution');
}
test();
Current output (Node v26.8.2):
SuppressedError: An error was suppressed during disposal.
at test (REPL10:3:3)
Both those errors are essential for debugging.
This has the exact same shape as two problems Node already solved for other "container" errors:
AggregateError.errors was silently swallowed during inspection — fixed in #43646 (tracked in #43645).
Error.cause was silently swallowed during inspection — fixed in #41002 (tracked in #40859).
SuppressedError.error / SuppressedError.suppressed fall into the same category and currently have no equivalent handling in formatError() (lib/internal/util/inspect.js).
What is the feature you are proposing to solve the problem?
Extend formatError() so that, similar to how cause and errors are already special-cased, the non-enumerable error and suppressed properties of a SuppressedError are always included in the inspected output (recursively, since a SuppressedError can itself wrap another SuppressedError when multiple disposals fail).
Desired output, roughly matching what the cause-chain rendering already does:
SuppressedError: An error was suppressed during disposal.
at test (…)
... {
[error]: Error: error during dispose
at Resource.[Symbol.dispose] (…)
...,
[suppressed]: Error: error during execution
at test (…)
...
}
What alternatives have you considered?
- Manually logging e.error and e.suppressed in application code — works, but requires every catch block to know it might be dealing with a SuppressedError.
- A userland [util.inspect.custom] patch on SuppressedError.prototype — works.
I believe a better out-of-the-box experience is required, rather than user-land patches. Workarounds shouldn't be necessary for a built-in error type tied to a TC39-standardized language feature
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in lib/internal/util/inspect.js at formatError(), comparing the existing special handling for cause and errors. Extend inspection so SuppressedError.error and SuppressedError.suppressed appear recursively, then verify util.inspect() and console.log() produce the requested nested output for disposal errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100