Redesign blocking route dev overlay and build errors#92638
Merged
aurorascharff merged 55 commits intocanaryfrom Apr 17, 2026
Merged
Redesign blocking route dev overlay and build errors#92638aurorascharff merged 55 commits intocanaryfrom
aurorascharff merged 55 commits intocanaryfrom
Conversation
Collaborator
Tests Passed |
Collaborator
Stats from current PR🔴 1 regression
📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📝 Changed Files (9 files)Files with changes:
View diffsapp-page-exp..ntime.dev.jsfailed to diffapp-page-exp..time.prod.jsfailed to diffapp-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsfailed to diffapp-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsfailed to diffapp-page.runtime.dev.jsfailed to diffapp-page.runtime.prod.jsfailed to diffserver.runtime.prod.jsDiff too large to display 📎 Tarball URL |
9b5f875 to
834deb8
Compare
- Centralize console error strings in blocking-route-messages.ts - Add interactive decision-tree guidance with collapsible sections - Use native HTML <details>/<summary> for accessible collapsibles - Extract error detection logic into blocking-route-error-details.ts - Extract old-style description components into blocking-route-descriptions.tsx - Add per-fix documentation links to nextjs.org/docs/messages - Extract specific API names (e.g. cookies()) from error messages
The dynamicBodyMessage now contains "request-time API" and the dynamic metadata/viewport messages contain "cookies()", which caused the fallback string heuristic to classify them as runtime variant instead of navigation variant. Fix by matching "A request-time API" only when not preceded by "Either" (which is unique to the dynamic template), and removing the cookies() check entirely. Made-with: Cursor
…ails Same misclassification bug as blocking-route-error-details.ts: dynamicMetadataMessage contains "cookies()" as an example, causing the heuristic to incorrectly classify it as runtime variant. Made-with: Cursor
… logic - Remove dead `generateMetadata` branch from `BlockingPageLoadErrorDescription` (never reached; metadata errors route through `DynamicMetadataErrorDescription`) - Remove unused `apiName` field (regex never matched, always null) - Colocate `getDynamicMetadataErrorDetails` into `blocking-route-error-details.ts` - Make `isRuntimeVariant` private (single source, no longer exported) - Fix grammar: "This indicate" → "This indicates" - Tighten `refinement` type to `'' | 'generateViewport'` Made-with: Cursor
With partial fallbacks (default in 16.3), generateStaticParams alone doesn't resolve the blocking-route error. You always need <Suspense> or loading.js. GSP prerender known values at build time as an optimization on top of that. Made-with: Cursor
…ixes with inline diffs, structured build messages - Add "What happened" / "Expected" explanation section between headline and stack trace - Restructure guidance: each fix is a collapsible with an inline code diff and docs link - First (most common) fix opens by default - All fix links point to blocking-route error page sections - Update build output messages with structured Cause/Triggers/Fix format Made-with: Cursor
834deb8 to
d2038f7
Compare
Build can't reliably distinguish Runtime from Dynamic causes, so merge runtimeBodyMessage/dynamicBodyMessage into a single bodyMessage (same for metadata and viewport). Reframe the fix list with "the right fix depends on which API triggered this and what behavior you want" instead of duplicating the next dev hint the framework already provides below. Revert all test snapshot changes to match canary — snapshots will be updated in a follow-up once messages are finalized. Made-with: Cursor
…ssification Revert the merged bodyMessage/metadataMessage/viewportMessage back to separate runtimeBodyMessage/dynamicBodyMessage etc. so the dev overlay can distinguish runtime APIs from uncached data. Restore the original isRuntimeVariant detection that matches on 'request-time API', 'cookies()', and 'Runtime data' — the tightened check broke classification when the second validation pass overrides with DynamicHoleKind.Dynamic. Also stamp syncDynamicErrorWithStack errors with runtimeBodyMessage since sync dynamic errors are always from runtime APIs. Made-with: Cursor
72976a4 to
eba3d2b
Compare
…untimeShell/StaticShell messages - isRuntimeVariant now checks for capital 'A request-time API' to only match runtimeBodyMessage, preventing fetch() from being misclassified as runtime variant - Swap RuntimeShell/StaticShell body/metadata/viewport message functions to match the pre-merge assignment Made-with: Cursor
… build messages - Replace tree diagram cards with compact code snippet cards (Vercel-themed, light/dark mode) - Update card names to match meeting decisions: Cache dynamic data, Add a new Suspense boundary, Lower access into a Suspense boundary, Let it block - Update build messages to include example APIs (cookies(), headers(), fetch(), etc.) - Fix isRuntimeVariant detection for new message format - Remove unused collapsible component, blocking-route-guidance, fix-diagrams, maybeGuidance variable - Clean up dead instantDevOverlay feature flag Made-with: Cursor
… structure Made-with: Cursor
… messages - Cards: merged Suspense cards into "Move within Suspense", GSP runtime-only with dashed conditional border, responsive grid (minmax 250px) - Wording: "Next.js encountered runtime/uncached data during the initial render" with streaming framing in description and build output - Build messages: aligned with overlay wording, expanded fix list for agents - Layout: removed sticky positioning, guidance flows naturally - Updated ~235 inline snapshots across 9 test files to match new wording Made-with: Cursor
- Fix isRuntimeVariant to match new message wording (checks "encountered runtime data" instead of old "Runtime data such as") - Restore ErrorCause rendering in InstantRuntimeError (was missing the "Caused by: Instant Validation" section) - Extract logBuildDebugHint into blocking-route-messages.ts and use it in both logDisallowedDynamicError and instant validation output Made-with: Cursor
Add the "next dev" / "next build --debug-prerender" debug hint to all 71 instant-validation build snapshots across 3 test files. Made-with: Cursor
Janka split dynamicBodyMessage into a shorter, more precise version (just fetch/connection) and a fallback dynamicOrRuntimeBodyMessage. Updates 53 inline snapshots across 3 test files. Made-with: Cursor
… fix typo Made-with: Cursor
eps1lon
reviewed
Apr 17, 2026
eps1lon
reviewed
Apr 17, 2026
eps1lon
reviewed
Apr 17, 2026
Made-with: Cursor
…ascharff/instant-error-overhaul
Made-with: Cursor
eps1lon
approved these changes
Apr 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
Redesigns the blocking-route error overlay for instant navigation errors with a distinct "Instant" overlay path, visual technique cards, and updated error wording framed around navigation impact.
Why?
The current overlay dumps every possible cause and fix in one block of text. The new design is friendlier — amber "Instant" badge, a short headline framed around navigation, and responsive code snippet cards showing each fix pattern.
Demo
cookies()): https://error-messages-overhaul-ibsl.labs.vercel.dev/scenario/26-cookies-ssr-no-instantfetch): https://error-messages-overhaul-ibsl.labs.vercel.dev/scenario/27-fetch-ssr-no-instantHow?
Overlay
errors.tsxforblocking-routeerrors without refinement — rendersInstantRuntimeErrorwith CodeFrame → description → technique cards → CallStack → ErrorCauseInstantGuidancecomponent with responsive CSS grid of fix technique cards (3 per variant)Build & CLI messages
blocking-route-messages.tsand deduplicated acrossdynamic-rendering.tsdynamicOrRuntimeBodyMessageadded for build-time static validation where the specific cause can't be pinpointed — lists all APIs (fetch(...),cookies(),headers(),params,searchParams,connection())isRuntimeVariant()replaces the oldincludes('cookies()')heuristic which broke because both templates mentioncookies()logBuildDebugHint()extracted and shared betweenlogDisallowedDynamicErrorand instant validation — adds "runnext dev" and "next build --debug-prerender" hints to instant validation build outputResults:

