Skip to content

NoFallbackError: replace internal-jargon message with actionable guidance#92936

Open
yogeshwaran-c wants to merge 1 commit intovercel:canaryfrom
yogeshwaran-c:fix/no-fallback-error-message
Open

NoFallbackError: replace internal-jargon message with actionable guidance#92936
yogeshwaran-c wants to merge 1 commit intovercel:canaryfrom
yogeshwaran-c:fix/no-fallback-error-message

Conversation

@yogeshwaran-c
Copy link
Copy Markdown

What?

Replace the NoFallbackError message from the unhelpful "Internal: NoFallbackError" with one that names the most common cause and links to the relevant docs.

Why?

NoFallbackError is an internal control-flow signal — the framework normally catches it and turns it into a 404 response, so the message is rarely seen by end users. But when it does leak to a server log (as reproduced in #87738 — a parent app router segment with dynamicParams: false plus a request whose params aren't in generateStaticParams()), the user sees:

```
Error: Internal: NoFallbackError
at (.next/server/chunks/ssr/babdf1ac..js:2:1128)
...
```

…which gives them no idea what went wrong, what to look for in their app, or where to read more. They have to chase it through Next.js source code to figure out the connection to dynamicParams.

How?

Replace the static message with one that names the common cause and links to the route segment config docs:

```
No fallback was rendered for this route, so the request returned a 404.
A common cause is dynamicParams: false on a parent segment combined with
a request whose params were not returned by generateStaticParams().
See https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams
```

Also switched from super(); this.message = ... (the old form) to the conventional super(message).

The error message is the only public surface of the class — no behavior change for the framework's normal catch-and-handle flow. Every instanceof NoFallbackError check in base-server.ts, next-server.ts, router-server.ts, etc., still works exactly as before.

Scope

Just the message. The PR deliberately does not try to enrich NoFallbackError with per-call context (which segment / route / params triggered it). That would require plumbing through every throw site (see grep for new NoFallbackError() in app-page.ts, app-route.ts, pages-handler.ts) and is a separate, larger change. The static message is already a substantial improvement on the no-info-at-all status quo.

Test plan

Added test/unit/no-fallback-error.test.ts with two cases:

  • The class is an Error subclass (sanity check).
  • The message contains dynamicParams, generateStaticParams, and a nextjs.org/docs/ URL — locks in the actionable wording so a future edit can't silently regress to "Internal: NoFallbackError".

npx jest test/unit/no-fallback-error.test.ts → 2 passed.

Fixes #87738

…ance

`NoFallbackError` is an internal control-flow signal — the framework
catches it and turns it into a 404. It's only seen by users when it
leaks to a server log, but when it does the message was

    Internal: NoFallbackError

which gives no guidance whatsoever. The reproduction in vercel#87738 — a
parent app router segment with `dynamicParams: false` plus a request
whose params aren't in `generateStaticParams()` — is exactly the case
where this leak surfaces, and users currently have no idea why their
route is 404'ing.

Replace the static message with one that names the most common cause
(`dynamicParams: false` on a parent + missing from
`generateStaticParams()`) and links to the route segment config docs.
Also switch from `super(); this.message = ...` to the conventional
`super(message)` form.

The message is the only public surface of the class; no behavior
changes for the framework's normal catch-and-handle flow. Added a
small unit test that locks in the message contains `dynamicParams`,
`generateStaticParams`, and a docs URL — so future edits don't
silently regress to "Internal: NoFallbackError".

Fixes vercel#87738
@yogeshwaran-c yogeshwaran-c marked this pull request as ready for review April 17, 2026 10:55
@nextjs-bot
Copy link
Copy Markdown
Contributor

Allow CI Workflow Run

  • approve CI run for commit: f5ce817

Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Poor error message when dynamicParams = false blocks child routes

2 participants