Skip to content

fix(core): preserve custom .stack getters in error/test formatter#35246

Merged
bartlomieju merged 2 commits into
mainfrom
fix/custom-stack-getter-formatting
Jun 17, 2026
Merged

fix(core): preserve custom .stack getters in error/test formatter#35246
bartlomieju merged 2 commits into
mainfrom
fix/custom-stack-getter-formatting

Conversation

@bartlomieju

Copy link
Copy Markdown
Member

Errors that expose a custom `.stack` getter, such as those produced by
Effect and other fiber runtimes, or a manually assigned `.stack` string,
were rendered with a single internal call-site frame instead of the
custom stack. `console.error` already showed the rich stack because it
formats via the `.stack` string, but letting the same error bubble to
the top-level handler or fail a test discarded it: those paths render
only the structured frames read from the private `#callSiteEvals` array,
which a custom `.stack` never populates.

When accessing `.stack` does not populate `#callSiteEvals`, the stack was
not produced by our `prepareStackTrace`, so the structured frames are not
authoritative. This marks such errors with a new `stack_is_custom` flag
on `JsError` and has the formatter emit the custom `.stack` string in
that case, matching Node.js.

Closes #35243

Errors that provide a custom `.stack` (e.g. Effect or other fiber
runtimes, or a manually assigned value) were rendered with an internal
call-site frame instead of their custom stack. `console.error` already
showed the rich stack because it formats via the `.stack` string, but
letting the error bubble to the top-level handler or fail a test
discarded it, since those paths render only the structured frames read
from the private #callSiteEvals array.

When accessing `.stack` does not populate #callSiteEvals, the stack was
not produced by our prepareStackTrace, so the structured frames are not
authoritative. Mark such errors with a new `stack_is_custom` flag on
JsError and have the formatter emit the custom `.stack` string instead,
matching Node.js.

Closes #35243
The stack_is_custom heuristic flagged any frame-less error whose .stack spans
more than one line. An error with a multi-line message (e.g. the "Unsupported
scheme ... Supported schemes:" list) has no frames and a multi-line .stack that
is just its "name: message" string, so it was wrongly classified as custom and
the formatter re-emitted the message tail, duplicating it.

Compare .stack against the default "name: message" representation and only
treat it as custom when it carries content beyond that header, so a multi-line
message is no longer mistaken for a stack.
@bartlomieju
bartlomieju enabled auto-merge (squash) June 17, 2026 08:39
@bartlomieju
bartlomieju merged commit 932bd1e into main Jun 17, 2026
265 of 270 checks passed
@bartlomieju
bartlomieju deleted the fix/custom-stack-getter-formatting branch June 17, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stack traces from custom .stack getters (Effect, fiber runtimes) are discarded by the error/test formatter

1 participant