Skip to content

fix(dev): cache sourcemap consumer per bundle in error handler - #4454

Open
danielroe wants to merge 2 commits into
nitrojs:mainfrom
danielroe:fix/dev-sourcemap
Open

fix(dev): cache sourcemap consumer per bundle in error handler#4454
danielroe wants to merge 2 commits into
nitrojs:mainfrom
danielroe:fix/dev-sourcemap

Conversation

@danielroe

@danielroe danielroe commented Jul 21, 2026

Copy link
Copy Markdown
Member

🔗 Linked issue

❓ Type of change

  • 📖 Documentation (updates to the documentation, readme, or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

spotted this while investigating a Nuxt rspack dev CI failure in nuxt/nuxt#35751 - rendering any SSR error page either hung for seconds or flooded the log with:

[error] unreachable (repeated 666 times)

in nitro, the dev error handler's sourceLoader builds a fresh SourceMapConsumer for every stack frame: youch-core caches by frame.fileName, but we mutate it to the original source before returning, so every app frame comes back in as the same bundle path and misses the cache.

this is particularly painful for rspaack because it's one big file and one multi-MB .mjs.map re-parsed dozens of times per error additionally, source-map@0.7's wasm consumer throws unreachable on some rspack maps, re-thrown per frame with no try/catch.

vite is unaffected since it serves native ESM.

this PR caches the consumer per .map file keyed on the bundle path so it's parsed once per request, wraps the parse and lookup so a map that trips the wasm decoder degrades to the un-enhanced frame instead of throwing, and destroys the consumers once the pass is done.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@danielroe
danielroe requested a review from pi0 as a code owner July 21, 2026 09:25
@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

@danielroe is attempting to deploy a commit to the Nitro Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 62c4e7dc-1fb6-4b08-abea-9ecb17e695b9

📥 Commits

Reviewing files that changed from the base of the PR and between 0ad448f and b480583.

📒 Files selected for processing (1)
  • src/runtime/internal/error/dev.ts

📝 Walkthrough

Walkthrough

Development stack-trace source-map loading now reuses lazily created consumers per map file, passes the cache through parsing, cleans up consumers afterward, and falls back to original frames when decoding fails.

Changes

Development source-map loading

Layer / File(s) Summary
Cached source-map resolution
src/runtime/internal/error/dev.ts
Adds cached, lazily created SourceMapConsumer instances keyed by bundled map filename and safely falls back when source-map resolution fails.
Stack-trace parsing lifecycle
src/runtime/internal/error/dev.ts
Passes the cache-backed loader into stack parsing and destroys all cached consumers in a finally block.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title uses a valid conventional commits format and matches the main dev error-handler sourcemap cache change.
Description check ✅ Passed The description matches the changeset by explaining the sourcemap consumer caching, fallback behavior, and cleanup in dev error handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Jul 21, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/nitro@4454

commit: b480583

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/runtime/internal/error/dev.ts (1)

141-141: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Silent failures with no warning on sourcemap decode/lookup errors.

Both the readFile(...).catch(() => {}) fallback in loadConsumer and the outer catch {} in sourceLoader (lines 176-179) swallow genuine decode/lookup failures (as opposed to the expected "no .map file" case) without any log, leaving no trail when sourcemap enhancement silently stops working.

As per coding guidelines, src/**/*.{ts,js}: "Prefer explicit errors over silent failures; use warnings for recoverable situations; throw for invalid states."

🩹 Proposed fix: warn on unexpected decode/lookup failures
     } catch {
-      // Some bundler-generated maps trip the source-map wasm decoder; degrade to
-      // the un-enhanced frame instead of throwing for every frame.
+      // Some bundler-generated maps trip the source-map wasm decoder; degrade to
+      // the un-enhanced frame instead of throwing for every frame.
+      console.warn(`[nitro] Failed to resolve source map for ${bundleFileName}`);
     }

Also applies to: 176-179

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/internal/error/dev.ts` at line 141, Update loadConsumer and
sourceLoader to distinguish an absent sourcemap file from decode or lookup
failures: retain the fallback for expected missing .map files, but emit a
warning through the existing logging mechanism when read, decode, or lookup
operations fail unexpectedly. Replace the empty catch blocks around rawSourceMap
loading and the outer sourceLoader handling without altering successful
sourcemap enhancement behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/runtime/internal/error/dev.ts`:
- Line 171: Update the path resolution in the frame-processing logic around
frame.fileName to use the corresponding pathe path utilities instead of
node:path, while preserving the existing dirname and resolve behavior.
- Around line 132-150: Update loadConsumer so SourceMapConsumer is initialized
with the appropriate wasm URL before constructing it from rawSourceMap. Keep the
initialization within the existing async loading flow and ensure initialization
failures remain handled consistently without silently skipping valid source-map
processing.

---

Nitpick comments:
In `@src/runtime/internal/error/dev.ts`:
- Line 141: Update loadConsumer and sourceLoader to distinguish an absent
sourcemap file from decode or lookup failures: retain the fallback for expected
missing .map files, but emit a warning through the existing logging mechanism
when read, decode, or lookup operations fail unexpectedly. Replace the empty
catch blocks around rawSourceMap loading and the outer sourceLoader handling
without altering successful sourcemap enhancement behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 796a8533-d5e0-4ab2-a7b9-fccd474db78c

📥 Commits

Reviewing files that changed from the base of the PR and between bfc2f5e and 0ad448f.

📒 Files selected for processing (1)
  • src/runtime/internal/error/dev.ts

Comment thread src/runtime/internal/error/dev.ts
Comment thread src/runtime/internal/error/dev.ts
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.

1 participant