-
Notifications
You must be signed in to change notification settings - Fork 4.4k
fix(console): print AggregateError wrapper instead of dropping it #29163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
robobun
wants to merge
10
commits into
main
Choose a base branch
from
farm/f653227f/aggregate-error-formatter
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
1955b21
fix(console): print AggregateError wrapper instead of dropping it
robobun deba3bc
[autofix.ci] apply automated fixes
autofix-ci[bot] b2f60ed
address review: walk all errors entries, reorder assertions, trim prose
robobun f2daa46
drop 'TODO: properly propagate exception upwards' debt tracker
robobun cd7672b
address review: DOMWrapper drain, wrapper→errors→cause order, drop st…
robobun 9f1c831
skip drain separator for DOMWrapper children
robobun d3dc440
revert drain-loop DOMWrapper routing, use distinctive child messages
robobun acfc93a
trigger ci retry — gate container tinycc fetch intermittent
robobun 4fcac71
restore ban-limits ratchet, use test.concurrent
robobun e7f4b9a
drop ban-limits TODO ratchet (gate hygiene)
robobun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| // https://github.com/oven-sh/bun/issues/29157 | ||
| // | ||
| // Bun's native `console.dir` / `console.log` formatter early-returned on any | ||
| // AggregateError, walking `.errors` and printing each entry as a top-level | ||
| // error — dropping the AggregateError wrapper's name, message, and stack. | ||
| // | ||
| // `Promise.any([Promise.reject(Error(""))]).catch(console.dir)` should print | ||
| // `AggregateError: ... { [errors]: [ ... ] }` like Node. Bun instead printed | ||
| // just the inner `Error` with no trace of the wrapper. | ||
| // | ||
| // Fix: removed the AggregateError early-return in `printErrorlikeObject` and | ||
| // taught `printErrorInstance` to walk the non-enumerable `.errors` array the | ||
| // same way it already walks `.cause`. | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| import { expect, test } from "bun:test"; | ||
| import { bunEnv, bunExe } from "harness"; | ||
|
|
||
| test("console.dir on AggregateError prints the wrapper, not just the inner errors", async () => { | ||
| await using proc = Bun.spawn({ | ||
| cmd: [ | ||
| bunExe(), | ||
| "-e", | ||
| `const err = new AggregateError([new Error("child1"), new Error("child2")], "wrapper"); | ||
| console.dir(err);`, | ||
| ], | ||
| env: bunEnv, | ||
| }); | ||
|
|
||
| const [stdout, stderr, exitCode] = await Promise.all([ | ||
| proc.stdout.text(), | ||
| proc.stderr.text(), | ||
| proc.exited, | ||
| ]); | ||
|
|
||
| expect(exitCode).toBe(0); | ||
|
Check warning on line 35 in test/regression/issue/29157.test.ts
|
||
| // The wrapper's name + message must be in the output. Pre-fix, this was | ||
| // absent — the formatter printed only "error: child1 ... error: child2". | ||
| expect(stdout).toContain("AggregateError"); | ||
| expect(stdout).toContain("wrapper"); | ||
|
robobun marked this conversation as resolved.
|
||
| // Children must still be printed below the wrapper. | ||
| expect(stdout).toContain("child1"); | ||
| expect(stdout).toContain("child2"); | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| }); | ||
|
|
||
| test("Promise.any rejection surfaces as an AggregateError, not a stray inner error", async () => { | ||
| await using proc = Bun.spawn({ | ||
| cmd: [ | ||
| bunExe(), | ||
| "-e", | ||
| `await Promise.any([Promise.reject(new Error("inner"))]).catch(console.dir);`, | ||
| ], | ||
| env: bunEnv, | ||
| }); | ||
|
|
||
| const [stdout, stderr, exitCode] = await Promise.all([ | ||
| proc.stdout.text(), | ||
| proc.stderr.text(), | ||
| proc.exited, | ||
| ]); | ||
|
|
||
| expect(exitCode).toBe(0); | ||
| // Pre-fix Bun printed `Error:` with no mention of AggregateError at all — | ||
| // exactly the bug from the issue report. | ||
| expect(stdout).toContain("AggregateError"); | ||
| expect(stdout).toContain("inner"); | ||
| }); | ||
|
|
||
| test("uncaught AggregateError rejection still shows the wrapper", async () => { | ||
| await using proc = Bun.spawn({ | ||
| cmd: [ | ||
| bunExe(), | ||
| "-e", | ||
| `await Promise.any([Promise.reject(new Error("a")), Promise.reject(new Error("b"))]);`, | ||
| ], | ||
| env: bunEnv, | ||
| }); | ||
|
|
||
| const [stdout, stderr, exitCode] = await Promise.all([ | ||
| proc.stdout.text(), | ||
| proc.stderr.text(), | ||
| proc.exited, | ||
| ]); | ||
|
|
||
| expect(exitCode).not.toBe(0); | ||
| // Uncaught rejection goes to stderr. The wrapper must appear there — the | ||
| // native error-reporter was fanning out `.errors` without printing the | ||
| // outer AggregateError at all. | ||
| expect(stderr).toContain("AggregateError"); | ||
| expect(stderr).toContain("a"); | ||
| expect(stderr).toContain("b"); | ||
| }); | ||
|
|
||
| test("AggregateError with a cause chain prints wrapper + errors + cause", async () => { | ||
| await using proc = Bun.spawn({ | ||
| cmd: [ | ||
| bunExe(), | ||
| "-e", | ||
| `const cause = new Error("root cause"); | ||
| const err = new AggregateError([new Error("child")], "wrapper", { cause }); | ||
| console.dir(err);`, | ||
| ], | ||
| env: bunEnv, | ||
| }); | ||
|
|
||
| const [stdout, stderr, exitCode] = await Promise.all([ | ||
| proc.stdout.text(), | ||
| proc.stderr.text(), | ||
| proc.exited, | ||
| ]); | ||
|
|
||
| expect(exitCode).toBe(0); | ||
| expect(stdout).toContain("AggregateError"); | ||
| expect(stdout).toContain("wrapper"); | ||
| expect(stdout).toContain("child"); | ||
| expect(stdout).toContain("root cause"); | ||
| }); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.