Link to the code that reproduces this issue
https://github.com/orcunbalcilar/nextjs-instant-validation-redirect-repro
To Reproduce
npm install && npm run dev
- Request
/dashboard twice — curl -s -o /dev/null http://localhost:3000/dashboard, then the same again.
The second request is the point: on the cold compile the message is suppressed (the devRenderDidError branch in getNavigationDisallowedDynamicReasons), so a single request looks like it does not reproduce.
/dashboard has a layout in the shape the Cache Components migration guide recommends — the request-bound read is kept out of the layout's top level, inside a <Suspense> boundary — and that shell redirects when a cookie is absent:
// app/dashboard/layout.tsx
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
<Suspense fallback={<p>loading shell…</p>}>
<Shell>{children}</Shell>
</Suspense>
)
}
async function Shell({ children }: { children: React.ReactNode }) {
const jar = await cookies()
if (!jar.get("seeded")) {
redirect("/elsewhere") // an ordinary gate, not an error
}
return <main>{children}</main>
}
Current vs. Expected behavior
Current. Every warm request to /dashboard logs:
Error: Route "/dashboard": Could not validate `instant` because the target segment was prevented
from rendering, likely due to the following error.
Error: An error occurred while attempting to validate instant UI. This error may be preventing the
validation from completing.
at DashboardLayout (app/dashboard/layout.tsx:13:5)
[cause]: Error: NEXT_REDIRECT
at Shell (app/dashboard/layout.tsx:23:13)
environmentName: 'Prefetch',
digest: 'NEXT_REDIRECT;replace;/elsewhere;307;'
Expected. A redirect() is deliberate control flow, not a render failure. I would expect validation to treat the route as "redirected, nothing to validate" and stay silent, the way catchError already declines to swallow the router sentinels.
Why this matters beyond the noise. While the redirect is thrown, validation for that request is inconclusive, so a genuine finding on the same route is not reported. Replace app/dashboard/page.tsx with a Server Component that does blocking IO:
import { connection } from "next/server"
export default async function DashboardPage() {
await connection()
return <p>dashboard</p>
}
then request /dashboard twice each way:
| Request |
Logged |
curl -H 'Cookie: seeded=1' .../dashboard (redirect does not fire) |
Next.js encountered uncached data … → blocking-prerender-dynamic — correct |
curl .../dashboard (redirect fires) |
only Could not validate \instant` …`; the real finding is gone |
So the message can hide the diagnostics it exists to surface.
Neither documented opt-out applies:
| Attempt |
Result |
export const instant = false on app/dashboard/layout.tsx |
no change — the reported line numbers shift by the added line, so the config is loaded, but the message stays |
export const instant = false on app/dashboard/page.tsx |
hard 500 — "instant" is a route segment config and can only be used when the segment is a Server Component module |
An interactive dashboard page is normally a Client Component, so the page-level opt-out is unavailable in exactly the case that needs it. #98666 reaches the same dead end from a different cause (next/root-params).
Where it comes from. Both call sites in packages/next/src/server/app-render/app-render.tsx (onError and onBrowserBailout) pass the thrown value straight to trackThrownErrorInNavigation, which wraps whatever it receives when there is no validation boundary on the component stack. Neither filters the router sentinels. isNextRouterError already exists for this, and its own doc comment describes the case precisely: "These errors are thrown by user code to perform navigation operations and interrupt the React render."
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.6.0: Fri Jul 31 19:18:49 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6000
Available memory (MB): 16384
Available CPU cores: 10
Binaries:
Node: 26.8.2
npm: 11.19.1
Yarn: 1.22.22
pnpm: 12.3.4
Relevant Packages:
next: 16.4.0-canary.32 // Latest available version is detected (16.4.0-canary.32).
eslint-config-next: N/A
react: 19.3.0
react-dom: 19.3.0
typescript: 7.0.2
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
cacheComponents, Redirects, Error Overlay
Which stage(s) are affected? (Select all that apply)
next dev (local)
Additional context
First hit on 16.3.5; reproduced unchanged on 16.4.0-canary.32. Found in a real app where the workspace layout gates on a session and a saved-project seed, so it fired on every cold entry to the dashboard. The reproduction above was reduced from it.
Link to the code that reproduces this issue
https://github.com/orcunbalcilar/nextjs-instant-validation-redirect-repro
To Reproduce
npm install && npm run dev/dashboardtwice —curl -s -o /dev/null http://localhost:3000/dashboard, then the same again.The second request is the point: on the cold compile the message is suppressed (the
devRenderDidErrorbranch ingetNavigationDisallowedDynamicReasons), so a single request looks like it does not reproduce./dashboardhas a layout in the shape the Cache Components migration guide recommends — the request-bound read is kept out of the layout's top level, inside a<Suspense>boundary — and that shell redirects when a cookie is absent:Current vs. Expected behavior
Current. Every warm request to
/dashboardlogs:Expected. A
redirect()is deliberate control flow, not a render failure. I would expect validation to treat the route as "redirected, nothing to validate" and stay silent, the waycatchErroralready declines to swallow the router sentinels.Why this matters beyond the noise. While the redirect is thrown, validation for that request is inconclusive, so a genuine finding on the same route is not reported. Replace
app/dashboard/page.tsxwith a Server Component that does blocking IO:then request
/dashboardtwice each way:curl -H 'Cookie: seeded=1' .../dashboard(redirect does not fire)Next.js encountered uncached data …→blocking-prerender-dynamic— correctcurl .../dashboard(redirect fires)Could not validate \instant` …`; the real finding is goneSo the message can hide the diagnostics it exists to surface.
Neither documented opt-out applies:
export const instant = falseonapp/dashboard/layout.tsxexport const instant = falseonapp/dashboard/page.tsx"instant" is a route segment config and can only be used when the segment is a Server Component moduleAn interactive dashboard page is normally a Client Component, so the page-level opt-out is unavailable in exactly the case that needs it. #98666 reaches the same dead end from a different cause (
next/root-params).Where it comes from. Both call sites in
packages/next/src/server/app-render/app-render.tsx(onErrorandonBrowserBailout) pass the thrown value straight totrackThrownErrorInNavigation, which wraps whatever it receives when there is no validation boundary on the component stack. Neither filters the router sentinels.isNextRouterErroralready exists for this, and its own doc comment describes the case precisely: "These errors are thrown by user code to perform navigation operations and interrupt the React render."Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 25.6.0: Fri Jul 31 19:18:49 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6000 Available memory (MB): 16384 Available CPU cores: 10 Binaries: Node: 26.8.2 npm: 11.19.1 Yarn: 1.22.22 pnpm: 12.3.4 Relevant Packages: next: 16.4.0-canary.32 // Latest available version is detected (16.4.0-canary.32). eslint-config-next: N/A react: 19.3.0 react-dom: 19.3.0 typescript: 7.0.2 Next.js Config: output: N/AWhich area(s) are affected? (Select all that apply)
cacheComponents, Redirects, Error Overlay
Which stage(s) are affected? (Select all that apply)
next dev (local)
Additional context
First hit on
16.3.5; reproduced unchanged on16.4.0-canary.32. Found in a real app where the workspace layout gates on a session and a saved-project seed, so it fired on every cold entry to the dashboard. The reproduction above was reduced from it.