Skip to content

feat(signals,solid,web): error hooks name where an error was thrown apart from where it was met - #3518

Merged
ryansolid merged 2 commits into
nextfrom
error-thrower-path
Sep 17, 2026
Merged

ryansolid merged 2 commits into
nextfrom
error-thrower-path

Conversation

@ryansolid

Copy link
Copy Markdown
Member

A C6 semantics refinement, surfaced while building the Sentry adapter against the linked build: both error hooks (and SSR_RENDER_ERROR_CONTAINED) reported only the boundary's owner path, so every component under one <Errored> grouped into one path — too coarse for issue grouping in exactly the tier the hook exists for (minified production, no source maps).

The two facts

  • ownerPath — where it was thrown. Labels root-first up the owner chain of the computation that threw: component labels and named primitives (the compiler's inner memos ride along by their default name). Falls back to the boundary's chain when the throw crossed nothing the runtime could name.
  • boundaryPath — where it was met (new). The same labels up the chain of the <Errored> that rendered its fallback (client and server), or the <Loading> that shipped the rejection (server, handling: "client"). What broke, and what the user saw.

<Loading> needed no special rule: on the client it doesn't catch (the rejection passes through to the nearest <Errored>, which is the met point); on the server it's the boundary whose handling the context already names.

Mechanics

  • Client — no new bookkeeping. The engine wraps the first landing in a StatusError whose source is the thrower, and keeps that instance as the error propagates; CollectionQueue.notify already had it. reportClientError takes it as a third argument.
  • ServerrunWithOwner and the memo pull's inlined twin stamp the error into a WeakMap<object, Owner> as it escapes (first wins, object errors only, NotReadyError skipped). reportServerError reads it. Component bodies, effects and async attempts all run through those scopes, so ["<App>", "<Loading>", "<Child>"] comes out for the fragment case without a per-site change.
  • FindingSSR_RENDER_ERROR_CONTAINED is located at the throw; data.boundaryPath names the boundary beside data.boundary.

The "boundary" record is unchanged: it is about the boundary, and joins the finding by id.

Verification

signals 2760 · solid 623 + 825 types · web 1001 + 185 types. Hook specs on both sides and the server finding specs assert the split (<App> › <Errored> › <Bad> thrown / <App> › <Errored> met). One cap: hydrating 19.85 → 19.90 KB, +41 B for the second path over a baseline that sat 1 B under its cap; the other scenarios moved within noise. RFC 03/08/12 updated; changeset for @solidjs/signals, solid-js, @solidjs/web.

Consumer side: the @sentry/solid-2 draft (in sentry-javascript, unpublished until an rc carries this) tags solid.owner and solid.boundary from the pair.

@changeset-bot

changeset-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 038470f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@solidjs/signals Patch
solid-js Patch
@solidjs/web Patch
test-integration Patch
@solidjs/element Patch
@solidjs/h Patch
@solidjs/html Patch
@solidjs/universal Patch
@solidjs/babel-plugin Patch
@solidjs/compiler Patch
@solidjs/diagnostics Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coveralls

coveralls commented Sep 17, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 35260411368

Coverage remained the same at 71.304%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1035
Covered Lines: 783
Line Coverage: 75.65%
Relevant Branches: 798
Covered Branches: 524
Branch Coverage: 65.66%
Branches in Coverage %: Yes
Coverage Strength: 15.06 hits per line

💛 - Coveralls

@codspeed

codspeed Bot commented Sep 17, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 172 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing error-thrower-path (038470f) with next (5a0a5f2)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

ryansolid and others added 2 commits September 17, 2026 11:29
…part from where it was met

`ownerPath` on `ClientErrorContext`/`ServerErrorContext` is now where the
error was THROWN — the labels up the owner chain of the computation that
threw — with the boundary's chain as the fallback when the throw crossed
nothing the runtime could name. `boundaryPath` is where it was MET: the
`<Errored>` that rendered its fallback, or the `<Loading>` that shipped
the rejection (`handling: "client"`). Before, both sides reported the
boundary's chain, so every component under one boundary grouped into one
path — too coarse for the tier the hook exists for (minified prod, no
source maps).

Client: the engine's `StatusError` wrapper already names the thrower
(`source`, made at the first landing, kept downstream); `notify` passes it
through. Server: `runWithOwner` and the memo pull's inlined twin stamp the
error into a WeakMap as it escapes (first wins, object errors only,
`NotReadyError` skipped); `reportServerError` reads it. The
`SSR_RENDER_ERROR_CONTAINED` finding follows: `ownerPath` locates the
throw, `data.boundaryPath` names the boundary beside `data.boundary`.

Hydrating cap 19.85 -> 19.90 KB (+41 B over a baseline 1 B under its cap).

Co-authored-by: Claude via Cursor <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Record bundle measurements after rebasing thrower and boundary paths over current next.\n\n— GPT-5.6 Sol via Cursor

Co-authored-by: Cursor <cursoragent@cursor.com>
@ryansolid
ryansolid merged commit 7624320 into next Sep 17, 2026
7 checks passed
ryansolid added a commit that referenced this pull request Sep 17, 2026
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.

2 participants