mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 00:09:23 +02:00
[PR #912] [MERGED] fix(app-router): surface Error.cause in dev-server error output #942
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#942
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/cloudflare/vinext/pull/912
Author: @james-elicx
Created: 4/26/2026
Status: ✅ Merged
Merged: 4/26/2026
Merged by: @james-elicx
Base:
main← Head:claude/lucid-maxwell-451364📝 Commits (2)
e1cce29fix(app-router): flatten Error.cause chain into dev-server error output0ce5f54fix: address bonk review feedback📊 Changes
4 files changed (+400 additions, -7 deletions)
View changed files
📝
packages/vinext/src/entries/app-rsc-entry.ts(+19 -1)➕
packages/vinext/src/utils/error-cause.ts(+107 -0)📝
tests/__snapshots__/entry-templates.test.ts.snap(+108 -6)➕
tests/error-cause.test.ts(+166 -0)📄 Description
Summary
Vite's dev-server "Internal server error:" formatter (
buildErrorMessageinvite-plus-core) builds output fromerr.messageanderr.stackonly, silently droppingerr.cause. A wrapper likenew Error("Failed query", { cause: pgError })would surface in the dev console as justFailed query— the actualECONNREFUSED, role-missing, or workerd socket error in.causewas invisible.This PR adds
flattenErrorCauses(err), called at the App Router RSC handler boundary before any error escapes to Vite. It walks the.causechain (depth-capped, cycle-safe) and embeds each cause's message intoerr.messageand stack frames intoerr.stackasatlines (so they survive Vite'scleanStack/^\s*at/filter).Before
After
Notes
Symbol.for("vinext.errorCausesFlattened")so Node'sutil.inspectoutput (which already shows.causesince Node 16.9) is unaffected — no doubled cause rendering in prod logs.console.error(err)→util.inspect, which already shows.cause, so no change needed there.__sanitizeErrorForClient,rscOnError,app-ssr-entry) also exclude cause from their hash input — different errors with different causes can collide on the same digest. Happy to do that as a follow-up if wanted.Test plan
flattenErrorCausesintests/error-cause.test.ts— 10 tests including a direct repro that mirrors Vite's formatter and assertsECONNREFUSEDis dropped before flattening and surfaced after; plus multi-level chains, idempotency, cyclic graphs, non-Error causes,null/undefined/string inputs, and marker non-enumerabilitytests/__snapshots__/entry-templates.test.ts.snap(6 snapshots) reflect the try/catch around_handleRequestvp checkpasses on all changed files🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.