Skip to content

feat(engine): report failing views with source-mapped stack traces - #708

Draft
romain-pm wants to merge 2 commits into
mainfrom
feat/dev-error-surfacing
Draft

feat(engine): report failing views with source-mapped stack traces#708
romain-pm wants to merge 2 commits into
mainfrom
feat/dev-error-surfacing

Conversation

@romain-pm

Copy link
Copy Markdown

Closes #700 — part of EPIC #698 (developer experience).

Problem

A view that throws is invisible where a developer looks. Jahia replaces the failed fragment with <!-- Module error : … --> (AbstractFilter, which includes the message in development mode and hides it in production), so the page still returns 200 and nothing on screen says anything broke. The exception does reach the log, but its JavaScript frames point inside the built bundle:

at <js>.:=>(my-module/dist/server/index.js:3937)

The build already emits a source map next to that bundle. Nothing consumed it.

Change

  • SourceMaps (new) reads the map shipped next to a module's server bundle, decodes its VLQ mappings, and resolves generated positions back to module sources. Maps are parsed on first use and dropped when the module is unregistered, so a redeploy re-reads them. Frames it cannot map — the library, the engine, Java frames — are left untouched.
  • JSScript logs the failure with the mapped stack, and in development mode returns a visible, HTML-escaped error box in place of the fragment. In production it rethrows exactly what it caught: unchanged behaviour, plus the new log line.
  • No new dependency: the map is parsed with Jackson, already used by this module.

Frames now read:

at <js>.:=>(my-module/src/react/server/views/testCrashingView/TestCrashingView.tsx:11)

Verification

Unit: 9 new tests over VLQ decoding, segment lookup (with and without a column, unmapped lines, out-of-range lines) and frame rewriting — mvn test -pl javascript-modules-engine-java → 26 tests, 0 failures.

Live, on two Jahia 8.2 instances differing only in operating mode, rendering the test module's existing testCrashingView:

development production
Page error box in place of the fragment, rest of the page intact unchanged (exception propagates as before)
Stack mapped to TestCrashingView.tsx:11 — the failing line
Log mapped trace mapped trace

Notes for the reviewer

  • No e2e test: the box is mode-dependent and the suite's instance mode is not guaranteed, so asserting it in Cypress would be brittle. The unit tests cover the mapping; the box itself is a five-line branch.
  • Everything interpolated into the box is HTML-escaped — an error message is module-controlled data, not markup.
  • The box is deliberately plain (inline styles, no external CSS) so it renders inside any layout.

When a view threw, Jahia replaced the fragment with an HTML comment and
logged an exception whose JavaScript frames pointed inside the module's
bundle (`dist/server/index.js:3937`). Both halves of that are unhelpful: the
failure is invisible on the page unless you read the source, and the stack
does not say which file you wrote is at fault.

The engine now reads the source map the build already emits next to a
module's server bundle, and rewrites JS frames back to module sources —
`src/components/Foo/default.server.tsx:12`. Maps are parsed on first use and
dropped when a module is unregistered, so a redeploy picks up new sources.
Frames without a map (the library, the engine itself) are left untouched.

In development mode a failing view also renders a visible, HTML-escaped error
box in place of its fragment, carrying the message and the mapped stack. In
production the exception propagates exactly as before; only the new log line
is added.

Verified on two Jahia 8.2 instances, one in each mode, against the test
module's crashing view: the box appears in development with the frame mapped
to TestCrashingView.tsx:11 (the failing line), production output is unchanged,
and both modes log the mapped trace. Nine unit tests cover the VLQ decoding,
segment lookup and frame rewriting.

Closes #700
@github-actions

Copy link
Copy Markdown

📝 Documentation Guidelines

Thank you for contributing to our documentation! To ensure your contributions meet our standards, please review these resources:

This comment is posted automatically when changes are detected in the docs/ folder.

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown

🦜 Chachalog

javascript-modules minor
  • A view that throws now reports itself. In development mode the failing fragment is replaced by a visible error box holding the message and the stack trace, instead of an HTML comment that only the page source revealed. Stack traces — in the box and in the server log, in every mode — have their positions mapped back to the module's own sources through the source map shipped next to the server bundle, so frames read src/components/Foo/default.server.tsx:12 rather than dist/server/index.js:3937. Production rendering is unchanged. (Dev error surfacing: visible errors, source-mapped stacks #700)

Create a new entry online or run npx chachalog@0.5.2 prompt to create a new entry locally.

The class comment claimed production swallows a failing view into an HTML
comment while development stays silent. It is the other way around, and
neither half was quite right: AbstractFilter#getContentForError emits the
comment in both modes — with the message in development, with a timestamp
pointing at the logs in production — and a failure landing higher in the
render chain propagates as a server error instead. No behaviour change.
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.

Dev error surfacing: visible errors, source-mapped stacks

1 participant