Skip to content

Keep the client-error status when the error page cannot be rendered - #98103

Open
dennytosp wants to merge 3 commits into
vercel:canaryfrom
dennytosp:fix/preserve-client-error-status
Open

Keep the client-error status when the error page cannot be rendered#98103
dennytosp wants to merge 3 commits into
vercel:canaryfrom
dennytosp:fix/preserve-client-error-status

Conversation

@dennytosp

Copy link
Copy Markdown

Fixes #94278, #92527, #92141 — one shared root cause.

  • Symptom: a pathname with broken percent-encoding (/%A0, /50%%) responds 500
    instead of 400. OPTIONS/POST on a static asset (/_next/static/chunks/*.js)
    responds 500 instead of 405.
  • Root cause: the server sets the correct 4xx first, then renders the matching error
    page (/400, /405). An app-router-only app with a catch-all route has no such page,
    so that render fails and the fallback branch hardcodes res.statusCode = 500.
  • Verified: req.url is still the malformed URL during the re-render, so the second
    render throws the same error. For static assets the 405 guard at router-server.ts:653
    runs correctly, but the status is overwritten afterwards by the fallback.
  • Change: keep the original 4xx instead of forcing 500; the plain-text body uses a
    reason phrase matching the status.
  • File: packages/next/src/server/base-server.ts (+43/-2)
  • For reviewers: two stale PRs cover the same ground — fix(router-server): return 400 instead of 500 for malformed URLs when… #94283 and fix(routing): return 404 for dynamic segments with un-decodable percent-encoded sequences #92557.
    fix(router-server): return 400 instead of 500 for malformed URLs when… #94283 patches router-server.ts, but tracing shows that code path is never reached.
  • Tests: 4 new (test/production/app-dir/client-error-status-fallback), passing on
    both turbopack and webpack.
  • Regression: 1101 passed / 5 skipped across 10 suites (middleware-general,
    500-page, custom-error-500, custom-error, 404-page-custom-error,
    error-handler-not-found-req-url, pages-dir/production, file-serving).

dennytosp and others added 3 commits August 26, 2026 21:41
The server sets a 4xx before trying to render an error page for it: 400 for
a pathname that fails to decode, 405 for a disallowed method on a static
asset. When no matching error page exists — an app-router-only app with a
catch-all route, for instance — that render fails and the fallback used to
overwrite the status with 500, so malformed requests and stray OPTIONS
probes were reported as server errors.

Preserve the original 4xx and respond with a matching plain-text body.
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.

Malformed Request URL causes 500 response

1 participant