diff --git a/docs/01-app/03-api-reference/07-adapters/02-creating-an-adapter.mdx b/docs/01-app/03-api-reference/07-adapters/02-creating-an-adapter.mdx index 081b135bbbb6..d3e51f2db4fd 100644 --- a/docs/01-app/03-api-reference/07-adapters/02-creating-an-adapter.mdx +++ b/docs/01-app/03-api-reference/07-adapters/02-creating-an-adapter.mdx @@ -42,6 +42,7 @@ export interface NextAdapter { ctx: { phase: PHASE_TYPE nextVersion: string + projectDir: string } ) => Promise | NextConfigComplete onBuildComplete?: (ctx: { diff --git a/docs/01-app/03-api-reference/07-adapters/03-api-reference.mdx b/docs/01-app/03-api-reference/07-adapters/03-api-reference.mdx index 4567c187bd4c..beac22e568e4 100644 --- a/docs/01-app/03-api-reference/07-adapters/03-api-reference.mdx +++ b/docs/01-app/03-api-reference/07-adapters/03-api-reference.mdx @@ -12,6 +12,7 @@ Called for any CLI command that loads the `next.config.js` file to allow modific - `config`: The complete Next.js configuration object - `context.phase`: The current build phase (see [phases](/docs/app/api-reference/config/next-config-js#phase)) - `context.nextVersion`: Version of Next.js being used +- `context.projectDir`: Absolute path to the Next.js project directory **Returns:** The modified configuration object (can be async) diff --git a/packages/next/.storybook/decorators/use-overlay-reducer.ts b/packages/next/.storybook/decorators/use-overlay-reducer.ts index 88a4002151ef..b61c59edb8c5 100644 --- a/packages/next/.storybook/decorators/use-overlay-reducer.ts +++ b/packages/next/.storybook/decorators/use-overlay-reducer.ts @@ -11,6 +11,7 @@ import { ACTION_BUILDING_INDICATOR_HIDE, ACTION_BUILDING_INDICATOR_SHOW, ACTION_CACHE_INDICATOR, + ACTION_INSTANT_ERRORS_CLEAR, ACTION_INSTANT_NAVS_TOGGLE, ACTION_INSTANT_NAVS_RESET, ACTION_DEBUG_INFO, @@ -88,6 +89,7 @@ export function useStorybookOverlayReducer(initialState?: OverlayState) { case ACTION_RENDERING_INDICATOR_HIDE: case ACTION_RENDERING_INDICATOR_SHOW: case ACTION_CACHE_INDICATOR: + case ACTION_INSTANT_ERRORS_CLEAR: case ACTION_INSTANT_NAVS_TOGGLE: case ACTION_INSTANT_NAVS_RESET: case ACTION_STATIC_INDICATOR: diff --git a/packages/next/errors.json b/packages/next/errors.json index eb11c7890745..a0d180d3b8bd 100644 --- a/packages/next/errors.json +++ b/packages/next/errors.json @@ -1244,8 +1244,13 @@ "1243": "This \"use cache\" has a dynamic cache life that was propagated to its parent.", "1244": "A \"use cache\" with short \\`expire\\` (under 5 minutes) is nested inside another \"use cache\" that has no explicit \\`cacheLife\\`, which is not allowed during prerendering. Add \\`cacheLife()\\` to the outer \"use cache\" to choose whether it should be prerendered (with longer \\`expire\\`) or remain dynamic (with short \\`expire\\`). Read more: https://nextjs.org/docs/messages/nested-use-cache-no-explicit-cachelife", "1245": "A \"use cache\" with zero \\`revalidate\\` is nested inside another \"use cache\" that has no explicit \\`cacheLife\\`, which is not allowed during prerendering. Add \\`cacheLife()\\` to the outer \"use cache\" to choose whether it should be prerendered (with non-zero \\`revalidate\\`) or remain dynamic (with zero \\`revalidate\\`). Read more: https://nextjs.org/docs/messages/nested-use-cache-no-explicit-cachelife", - "1246": "Could not validate instant UI because an expected segment was not rendered.", - "1247": "\\`experimental.cssChunking: \"graph\"\\` is only supported with Turbopack. Please remove the option or run Next.js with Turbopack in %s.", - "1248": "\\`experimental.cssChunking: \"strict\"\\` is only supported with webpack. Please remove the option or run Next.js with webpack in %s.", - "1249": "\\`experimental.cssChunking: false\\` is only supported with webpack. Please remove the option or run Next.js with webpack in %s." + "1246": "Route \"%s\": Next.js encountered uncached data during the initial render or a navigation.\\n\\n\\`fetch(...)\\` or \\`connection()\\` accessed under \\`\\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\\n\\nWays to fix this:\\n - Cache the data access with \\`\"use cache\"\\`\\n - Provide a placeholder with \\`\\` around the data access\\n - Set \\`export const instant = false\\` to allow a blocking route\\n\\nLearn more: https://nextjs.org/docs/messages/blocking-route", + "1247": "Route \"%s\": Next.js encountered runtime data during the initial render or a navigation.\\n\\n\\`cookies()\\`, \\`headers()\\`, \\`params\\`, or \\`searchParams\\` accessed under \\`\\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\\n\\nWays to fix this:\\n - Use \\`generateStaticParams\\` to make route params static\\n - Provide a placeholder with \\`\\` around the data access\\n - Set \\`export const instant = false\\` to allow a blocking route\\n\\nLearn more: https://nextjs.org/docs/messages/blocking-route", + "1248": "Could not validate instant UI because an expected segment was not rendered.", + "1249": "Route \"%s\": Next.js encountered uncached data during the initial render or a navigation.\\n\\n\\`fetch(...)\\` or \\`connection()\\` accessed outside of \\`\\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\\n\\nWays to fix this:\\n - Cache the data access with \\`\"use cache\"\\`\\n - Provide a placeholder with \\`\\` around the data access\\n - Set \\`export const instant = false\\` to allow a blocking route\\n\\nLearn more: https://nextjs.org/docs/messages/blocking-route", + "1250": "Route \"%s\": Next.js encountered runtime data during the initial render or a navigation.\\n\\n\\`cookies()\\`, \\`headers()\\`, \\`params\\`, or \\`searchParams\\` accessed outside of \\`\\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\\n\\nWays to fix this:\\n - Use \\`generateStaticParams\\` to make route params static\\n - Provide a placeholder with \\`\\` around the data access\\n - Set \\`export const instant = false\\` to allow a blocking route\\n\\nLearn more: https://nextjs.org/docs/messages/blocking-route", + "1251": "Route \"%s\": Next.js encountered runtime data during the initial render or a navigation.\\n\\n\\`cookies()\\`, \\`headers()\\`, \\`params\\`, or \\`searchParams\\` accessed outside of \\`\\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\\n\\nWays to fix this:\\n - Provide a placeholder with \\`\\` around the data access\\n - Use \\`generateStaticParams\\` to make route params static\\n - Set \\`export const instant = false\\` to allow a blocking route\\n\\nLearn more: https://nextjs.org/docs/messages/blocking-route", + "1252": "\\`experimental.cssChunking: \"graph\"\\` is only supported with Turbopack. Please remove the option or run Next.js with Turbopack in %s.", + "1253": "\\`experimental.cssChunking: \"strict\"\\` is only supported with webpack. Please remove the option or run Next.js with webpack in %s.", + "1254": "\\`experimental.cssChunking: false\\` is only supported with webpack. Please remove the option or run Next.js with webpack in %s." } diff --git a/packages/next/src/build/adapter/build-complete.ts b/packages/next/src/build/adapter/build-complete.ts index 86db2bed9d77..cbd3ce28b81d 100644 --- a/packages/next/src/build/adapter/build-complete.ts +++ b/packages/next/src/build/adapter/build-complete.ts @@ -379,6 +379,10 @@ export interface NextAdapter { * nextVersion is the current version of Next.js being used */ nextVersion: string + /** + * projectDir is the absolute directory the Next.js application is in + */ + projectDir: string } ) => Promise | NextConfigComplete onBuildComplete?: (ctx: { diff --git a/packages/next/src/next-devtools/dev-overlay/components/instant/instant-guidance-data.ts b/packages/next/src/next-devtools/dev-overlay/components/instant/instant-guidance-data.ts index b776f8a8e667..1d6207dcb489 100644 --- a/packages/next/src/next-devtools/dev-overlay/components/instant/instant-guidance-data.ts +++ b/packages/next/src/next-devtools/dev-overlay/components/instant/instant-guidance-data.ts @@ -486,7 +486,7 @@ export type GuidanceKind = | 'sync-io' | 'sync-io-client' -export type GuidanceVariant = 'runtime' | 'navigation' +export type GuidanceVariant = 'runtime' | 'dynamic' export const DOCS_URLS: Record = { 'blocking-route': 'https://nextjs.org/docs/messages/blocking-route', @@ -562,6 +562,9 @@ export const EXPLANATIONS: Record = { 'This value would be evaluated during the prerender and fixed at build time, instead of recomputed on each visit.', } +export const BLOCKING_ROUTE_NAVIGATION_EXPLANATION = + 'This prevents the navigation from being instant, leading to a slower user experience.' + const syncCardsByCause: Record = { 'Math.random()': syncMathCards, 'Date.now()': syncDateCards, @@ -601,7 +604,7 @@ export function getCards( ): FixCard[] { switch (kind) { case 'blocking-route': - return variant === 'navigation' ? dynamicCards : runtimeCards + return variant === 'dynamic' ? dynamicCards : runtimeCards case 'metadata': return variant === 'runtime' ? metadataRuntimeCards : metadataDynamicCards case 'viewport': diff --git a/packages/next/src/next-devtools/dev-overlay/container/errors.test.ts b/packages/next/src/next-devtools/dev-overlay/container/errors.test.ts index dae0dfdfcfb8..395f7daad31c 100644 --- a/packages/next/src/next-devtools/dev-overlay/container/errors.test.ts +++ b/packages/next/src/next-devtools/dev-overlay/container/errors.test.ts @@ -1,11 +1,13 @@ import { createDynamicBodyError, + createDynamicBodyErrorInNavigation, createDynamicMetadataError, createDynamicOrRuntimeBodyError, createDynamicOrRuntimeMetadataError, createDynamicOrRuntimeViewportError, createDynamicViewportError, createRuntimeBodyError, + createRuntimeBodyErrorInNavigation, createRuntimeMetadataError, createRuntimeViewportError, } from '../../../server/app-render/blocking-route-messages' @@ -24,14 +26,6 @@ import { const ROUTE = '/example' -// Every detection helper in errors.tsx walks the user-facing error message -// produced by the server-side factories in `blocking-route-messages.ts` and -// `sync-io-messages.ts`. These tests guard the contract between the two -// modules: if a factory's wording shifts in a way the detector can't -// recognize, classification silently falls back to "not an instant error" -// and the overlay shows the wrong UI. Three regressions in this exact spot -// during the redesign motivated this test. - describe('isRuntimeVariant', () => { it('returns true for runtime body factory output', () => { expect(isRuntimeVariant(createRuntimeBodyError(ROUTE).message)).toBe(true) @@ -128,24 +122,48 @@ describe('isSyncIOClientError', () => { }) describe('getBlockingRouteErrorDetails', () => { - it('classifies createRuntimeBodyError as blocking-route + runtime', () => { + it('classifies createRuntimeBodyError as blocking-route + runtime (SSR-only)', () => { expect(getBlockingRouteErrorDetails(createRuntimeBodyError(ROUTE))).toEqual( - { type: 'blocking-route', variant: 'runtime' } + { type: 'blocking-route', variant: 'runtime', inNavigation: false } ) }) - it('classifies createDynamicBodyError as blocking-route + navigation', () => { + it('classifies createDynamicBodyError as blocking-route + dynamic (SSR-only)', () => { expect(getBlockingRouteErrorDetails(createDynamicBodyError(ROUTE))).toEqual( - { type: 'blocking-route', variant: 'navigation' } + { type: 'blocking-route', variant: 'dynamic', inNavigation: false } ) }) - it('classifies createDynamicOrRuntimeBodyError as blocking-route + navigation', () => { + it('classifies createRuntimeBodyErrorInNavigation as blocking-route + runtime + inNavigation', () => { + expect( + getBlockingRouteErrorDetails(createRuntimeBodyErrorInNavigation(ROUTE)) + ).toEqual({ + type: 'blocking-route', + variant: 'runtime', + inNavigation: true, + }) + }) + + it('classifies createDynamicBodyErrorInNavigation as blocking-route + dynamic + inNavigation', () => { + expect( + getBlockingRouteErrorDetails(createDynamicBodyErrorInNavigation(ROUTE)) + ).toEqual({ + type: 'blocking-route', + variant: 'dynamic', + inNavigation: true, + }) + }) + + it('classifies createDynamicOrRuntimeBodyError as blocking-route + dynamic (SSR-only)', () => { // The "either" factory has no clear runtime signal — falls into the - // navigation branch by `isRuntimeVariant`. Documents current behavior. + // dynamic branch by `isRuntimeVariant`. Documents current behavior. expect( getBlockingRouteErrorDetails(createDynamicOrRuntimeBodyError(ROUTE)) - ).toEqual({ type: 'blocking-route', variant: 'navigation' }) + ).toEqual({ + type: 'blocking-route', + variant: 'dynamic', + inNavigation: false, + }) }) it('classifies createRuntimeMetadataError as dynamic-metadata + runtime', () => { @@ -154,16 +172,16 @@ describe('getBlockingRouteErrorDetails', () => { ).toEqual({ type: 'dynamic-metadata', variant: 'runtime' }) }) - it('classifies createDynamicMetadataError as dynamic-metadata + navigation', () => { + it('classifies createDynamicMetadataError as dynamic-metadata + dynamic', () => { expect( getBlockingRouteErrorDetails(createDynamicMetadataError(ROUTE)) - ).toEqual({ type: 'dynamic-metadata', variant: 'navigation' }) + ).toEqual({ type: 'dynamic-metadata', variant: 'dynamic' }) }) - it('classifies createDynamicOrRuntimeMetadataError as dynamic-metadata + navigation', () => { + it('classifies createDynamicOrRuntimeMetadataError as dynamic-metadata + dynamic', () => { expect( getBlockingRouteErrorDetails(createDynamicOrRuntimeMetadataError(ROUTE)) - ).toEqual({ type: 'dynamic-metadata', variant: 'navigation' }) + ).toEqual({ type: 'dynamic-metadata', variant: 'dynamic' }) }) it('classifies createRuntimeViewportError as dynamic-viewport + runtime', () => { @@ -172,16 +190,16 @@ describe('getBlockingRouteErrorDetails', () => { ).toEqual({ type: 'dynamic-viewport', variant: 'runtime' }) }) - it('classifies createDynamicViewportError as dynamic-viewport + navigation', () => { + it('classifies createDynamicViewportError as dynamic-viewport + dynamic', () => { expect( getBlockingRouteErrorDetails(createDynamicViewportError(ROUTE)) - ).toEqual({ type: 'dynamic-viewport', variant: 'navigation' }) + ).toEqual({ type: 'dynamic-viewport', variant: 'dynamic' }) }) - it('classifies createDynamicOrRuntimeViewportError as dynamic-viewport + navigation', () => { + it('classifies createDynamicOrRuntimeViewportError as dynamic-viewport + dynamic', () => { expect( getBlockingRouteErrorDetails(createDynamicOrRuntimeViewportError(ROUTE)) - ).toEqual({ type: 'dynamic-viewport', variant: 'navigation' }) + ).toEqual({ type: 'dynamic-viewport', variant: 'dynamic' }) }) it.each<[SyncIOApiType, string, string]>([ diff --git a/packages/next/src/next-devtools/dev-overlay/container/errors.tsx b/packages/next/src/next-devtools/dev-overlay/container/errors.tsx index c87316db391f..a0d19b6aeff2 100644 --- a/packages/next/src/next-devtools/dev-overlay/container/errors.tsx +++ b/packages/next/src/next-devtools/dev-overlay/container/errors.tsx @@ -28,6 +28,7 @@ import { type GuidanceKind, type GuidanceVariant, } from '../components/instant/instant-guidance' +import { BLOCKING_ROUTE_NAVIGATION_EXPLANATION } from '../components/instant/instant-guidance-data' import { CodeFrame } from '../components/code-frame/code-frame' import { ErrorOverlayCallStack } from '../components/errors/error-overlay-call-stack/error-overlay-call-stack' import { ErrorCause } from './runtime-error/error-cause' @@ -129,17 +130,18 @@ type HydrationErrorDetails = { type BlockingRouteErrorDetails = { type: 'blocking-route' - variant: 'navigation' | 'runtime' + variant: 'dynamic' | 'runtime' + inNavigation: boolean } type DynamicMetadataErrorDetails = { type: 'dynamic-metadata' - variant: 'navigation' | 'runtime' + variant: 'dynamic' | 'runtime' } type DynamicViewportErrorDetails = { type: 'dynamic-viewport' - variant: 'navigation' | 'runtime' + variant: 'dynamic' | 'runtime' } type SyncIOErrorDetails = { @@ -320,16 +322,31 @@ export function isSyncIOClientError(message: string): boolean { return match !== null && match[2] === '-client' } +// Detects errors emitted during navigation-phase instant validation: body +// errors from `createRuntimeBodyErrorInNavigation` / +// `createDynamicBodyErrorInNavigation` (SSR factories instead say "during +// the initial render"), and validation errors from +// `trackDynamicHoleInNavigation` / `getNavigationDisallowedDynamicReasons`. +export function isBlockingRouteInNavError(message: string): boolean { + return ( + message.includes('or a navigation') || + message.includes('Could not validate `unstable_instant`') || + message.includes('Could not validate instant UI') + ) +} + export function getBlockingRouteErrorDetails( error: Error ): null | ErrorDetails { const message = error.message + const inNavigation = isBlockingRouteInNavError(message) const isBlockingPageLoadError = message.includes('/blocking-route') if (isBlockingPageLoadError) { return { type: 'blocking-route', - variant: isRuntimeVariant(message) ? 'runtime' : 'navigation', + variant: isRuntimeVariant(message) ? 'runtime' : 'dynamic', + inNavigation, } } @@ -339,7 +356,7 @@ export function getBlockingRouteErrorDetails( if (isDynamicMetadataError) { return { type: 'dynamic-metadata', - variant: isRuntimeVariant(message) ? 'runtime' : 'navigation', + variant: isRuntimeVariant(message) ? 'runtime' : 'dynamic', } } @@ -349,7 +366,7 @@ export function getBlockingRouteErrorDetails( if (isBlockingViewportError) { return { type: 'dynamic-viewport', - variant: isRuntimeVariant(message) ? 'runtime' : 'navigation', + variant: isRuntimeVariant(message) ? 'runtime' : 'dynamic', } } @@ -540,10 +557,23 @@ Next.js version: ${props.versionInfo.installed} (${process.env.__NEXT_BUNDLER})\ errorType={errorType} errorMessage={ errorDetails.variant === 'runtime' - ? 'Next.js encountered runtime data during the initial render.' - : 'Next.js encountered uncached data during the initial render.' + ? errorDetails.inNavigation + ? 'Next.js encountered runtime data during a navigation.' + : 'Next.js encountered runtime data during the initial render.' + : errorDetails.inNavigation + ? 'Next.js encountered uncached data during a navigation.' + : 'Next.js encountered uncached data during the initial render.' + } + headerChildren={ + } - headerChildren={} onClose={isServerError ? undefined : onClose} debugInfo={debugInfo} error={error} diff --git a/packages/next/src/next-devtools/dev-overlay/dev-overlay.tsx b/packages/next/src/next-devtools/dev-overlay/dev-overlay.tsx index f0ac1350ffd8..ce5d42b13436 100644 --- a/packages/next/src/next-devtools/dev-overlay/dev-overlay.tsx +++ b/packages/next/src/next-devtools/dev-overlay/dev-overlay.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useRef, useState } from 'react' +import { createContext, useContext, useEffect, useRef, useState } from 'react' import { ShadowPortal } from './components/shadow-portal' import { ComponentStyles } from './styles/component-styles' import { ErrorOverlay } from './components/errors/error-overlay/error-overlay' @@ -9,6 +9,7 @@ import { DevToolsIndicator } from './components/devtools-indicator/devtools-indi import { PanelRouter } from './menu/panel-router' import { PanelRouterContext, type PanelStateKind } from './menu/context' import { useDevOverlayContext } from '../dev-overlay.browser' +import { ACTION_INSTANT_ERRORS_CLEAR, type DispatcherEvent } from './shared' export const RenderErrorContext = createContext<{ runtimeErrors: ReadyRuntimeError[] @@ -17,6 +18,26 @@ export const RenderErrorContext = createContext<{ export const useRenderErrorContext = () => useContext(RenderErrorContext) +// Dispatches `ACTION_INSTANT_ERRORS_CLEAR` whenever the page changes to a +// new non-empty value. The first non-empty value is recorded as a baseline +// (the route the user landed on) and does not trigger a clear. +function useClearInstantErrorsOnNav( + page: string, + dispatch: (action: DispatcherEvent) => void +) { + const baselinePageRef = useRef(null) + useEffect(() => { + if (page === '') return + if (baselinePageRef.current === null) { + baselinePageRef.current = page + return + } + if (page === baselinePageRef.current) return + baselinePageRef.current = page + dispatch({ type: ACTION_INSTANT_ERRORS_CLEAR, currentPath: page }) + }, [page, dispatch]) +} + export function DevOverlay() { const [selectedIndex, setSelectedIndex] = useState(-1) const { state, dispatch, getSquashedHydrationErrorDetails } = @@ -25,6 +46,8 @@ export function DevOverlay() { state.instantNavs ? 'instant-navs' : null ) + useClearInstantErrorsOnNav(state.page, dispatch) + const triggerRef = useRef(null) return ( diff --git a/packages/next/src/next-devtools/dev-overlay/shared.test.ts b/packages/next/src/next-devtools/dev-overlay/shared.test.ts new file mode 100644 index 000000000000..2419ca596064 --- /dev/null +++ b/packages/next/src/next-devtools/dev-overlay/shared.test.ts @@ -0,0 +1,99 @@ +import { + createDynamicBodyError, + createDynamicBodyErrorInNavigation, + createRuntimeBodyError, + createRuntimeBodyErrorInNavigation, +} from '../../server/app-render/blocking-route-messages' +import { getInstantErrorRoute, routeTemplateMatchesPath } from './shared' + +const STATIC_ROUTE = '/example' +const DYNAMIC_ROUTE_TEMPLATE = '/posts/[slug]' +const CATCH_ALL_ROUTE_TEMPLATE = '/docs/[...slug]' + +describe('getInstantErrorRoute', () => { + it('returns the route for an in-navigation runtime body error', () => { + expect( + getInstantErrorRoute(createRuntimeBodyErrorInNavigation(STATIC_ROUTE)) + ).toBe(STATIC_ROUTE) + }) + + it('returns the route for an in-navigation dynamic body error', () => { + expect( + getInstantErrorRoute( + createDynamicBodyErrorInNavigation(DYNAMIC_ROUTE_TEMPLATE) + ) + ).toBe(DYNAMIC_ROUTE_TEMPLATE) + }) + + it('returns the route for the unrendered-segment wrapper', () => { + const error = new Error( + `Route "${STATIC_ROUTE}": Could not validate instant UI because an expected segment was not rendered.\n\nUnrendered segment:\n app/example/page.tsx` + ) + expect(getInstantErrorRoute(error)).toBe(STATIC_ROUTE) + }) + + it('returns null for SSR-only body errors', () => { + expect(getInstantErrorRoute(createRuntimeBodyError(STATIC_ROUTE))).toBe( + null + ) + expect(getInstantErrorRoute(createDynamicBodyError(STATIC_ROUTE))).toBe( + null + ) + }) + + it('returns null for unrelated errors', () => { + expect(getInstantErrorRoute(new Error('regular bug'))).toBe(null) + }) + + it('returns null for non-Error inputs', () => { + expect(getInstantErrorRoute(null)).toBe(null) + expect(getInstantErrorRoute(undefined)).toBe(null) + expect(getInstantErrorRoute('string error')).toBe(null) + }) +}) + +describe('routeTemplateMatchesPath', () => { + it('matches identical static routes', () => { + expect(routeTemplateMatchesPath(STATIC_ROUTE, STATIC_ROUTE)).toBe(true) + }) + + it('does not match different static routes', () => { + expect(routeTemplateMatchesPath('/foo', '/bar')).toBe(false) + }) + + it('matches a dynamic template against a resolved URL', () => { + expect(routeTemplateMatchesPath(DYNAMIC_ROUTE_TEMPLATE, '/posts/123')).toBe( + true + ) + expect( + routeTemplateMatchesPath(DYNAMIC_ROUTE_TEMPLATE, '/posts/hello-world') + ).toBe(true) + }) + + it('does not match a dynamic template against a sibling route', () => { + expect(routeTemplateMatchesPath(DYNAMIC_ROUTE_TEMPLATE, '/users/123')).toBe( + false + ) + }) + + it('does not match a dynamic template against deeper path segments', () => { + expect( + routeTemplateMatchesPath(DYNAMIC_ROUTE_TEMPLATE, '/posts/2026/05/16') + ).toBe(false) + }) + + it('matches a catch-all template against multiple resolved segments', () => { + expect( + routeTemplateMatchesPath( + CATCH_ALL_ROUTE_TEMPLATE, + '/docs/getting-started' + ) + ).toBe(true) + expect( + routeTemplateMatchesPath( + CATCH_ALL_ROUTE_TEMPLATE, + '/docs/app/api-reference/functions/cookies' + ) + ).toBe(true) + }) +}) diff --git a/packages/next/src/next-devtools/dev-overlay/shared.ts b/packages/next/src/next-devtools/dev-overlay/shared.ts index 1d726d9c6041..0db34096c6dd 100644 --- a/packages/next/src/next-devtools/dev-overlay/shared.ts +++ b/packages/next/src/next-devtools/dev-overlay/shared.ts @@ -9,6 +9,9 @@ import { parseStack } from '../../server/lib/parse-stack' import { isConsoleError } from '../shared/console-error' import type { CacheIndicatorState } from './cache-indicator' import { readInstantNavCookieState } from './components/instant-navs/instant-nav-cookie' +import { isBlockingRouteInNavError } from './container/errors' +import { isDynamicRoute } from '../../shared/lib/router/utils/is-dynamic' +import { getRouteRegex } from '../../shared/lib/router/utils/route-regex' export type DevToolsConfig = { theme?: 'light' | 'dark' | 'system' @@ -107,6 +110,7 @@ export const ACTION_DEVTOOLS_SCALE = 'devtools-scale' export const ACTION_DEVTOOLS_CONFIG = 'devtools-config' export const ACTION_INSTANT_NAVS_TOGGLE = 'instant-navs-toggle' export const ACTION_INSTANT_NAVS_RESET = 'instant-navs-reset' +export const ACTION_INSTANT_ERRORS_CLEAR = 'instant-errors-clear' export const STORAGE_KEY_PANEL_POSITION_PREFIX = '__nextjs-dev-tools-panel-position' @@ -231,6 +235,11 @@ interface InstantNavResetAction { type: typeof ACTION_INSTANT_NAVS_RESET } +interface InstantErrorsClearAction { + type: typeof ACTION_INSTANT_ERRORS_CLEAR + currentPath: string +} + export type DispatcherEvent = | BuildOkAction | BuildErrorAction @@ -258,6 +267,7 @@ export type DispatcherEvent = | DevToolsConfigAction | CacheOnlyToggleAction | InstantNavResetAction + | InstantErrorsClearAction const REACT_ERROR_STACK_BOTTOM_FRAME_REGEX = // 1st group: new frame + v8 @@ -274,6 +284,33 @@ function getStackIgnoringStrictMode(stack: string | undefined) { return stack?.split(REACT_ERROR_STACK_BOTTOM_FRAME_REGEX)[0] } +export function getInstantErrorRoute(error: unknown): string | null { + if (!error || typeof error !== 'object') return null + const message = (error as Error).message + if (typeof message !== 'string') return null + if (!isBlockingRouteInNavError(message)) return null + // Most factories prefix `Route "":`; the missing-segment factory in + // `dynamic-rendering.ts` writes `Route: ` on its own line in the body. + const prefixMatch = /^Route "([^"]+)":/.exec(message) + if (prefixMatch) return prefixMatch[1] + const lineMatch = /\nRoute: (\S+)/.exec(message) + return lineMatch ? lineMatch[1] : null +} + +// The route stored on an instant error is the route *template* from +// `workStore.route` (e.g. `/foo/[slug]`), but the page we track in dev +// overlay state is the resolved URL (e.g. `/foo/123`). For dynamic routes +// we compile the template to a regex so the clear-on-nav reducer keeps +// errors whose template matches the page the user just landed on. +export function routeTemplateMatchesPath( + template: string, + path: string +): boolean { + if (template === path) return true + if (!isDynamicRoute(template)) return false + return getRouteRegex(template).re.test(path) +} + const shouldDisableDevIndicator = process.env.__NEXT_DEV_INDICATOR?.toString() === 'false' @@ -539,6 +576,17 @@ export function useErrorOverlayReducer( case ACTION_INSTANT_NAVS_RESET: { return { ...state, instantNavs: false } } + case ACTION_INSTANT_ERRORS_CLEAR: { + const remaining = state.errors.filter((event) => { + const route = getInstantErrorRoute(event.error) + if (route === null) return true + return routeTemplateMatchesPath(route, action.currentPath) + }) + if (remaining.length === state.errors.length) { + return state + } + return { ...state, errors: remaining } + } default: { return state } diff --git a/packages/next/src/server/app-render/blocking-route-messages.ts b/packages/next/src/server/app-render/blocking-route-messages.ts index cb1de77cb370..84801cc7a1d0 100644 --- a/packages/next/src/server/app-render/blocking-route-messages.ts +++ b/packages/next/src/server/app-render/blocking-route-messages.ts @@ -22,6 +22,30 @@ export function createDynamicBodyError(route: string): Error { ) } +export function createRuntimeBodyErrorInNavigation(route: string): Error { + return new Error( + `Route "${route}": Next.js encountered runtime data during the initial render or a navigation.\n\n` + + `\`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\n\n` + + `Ways to fix this:\n` + + ` - Provide a placeholder with \`\` around the data access\n` + + ` - Use \`generateStaticParams\` to make route params static\n` + + ` - Set \`export const instant = false\` to allow a blocking route\n\n` + + `Learn more: https://nextjs.org/docs/messages/blocking-route` + ) +} + +export function createDynamicBodyErrorInNavigation(route: string): Error { + return new Error( + `Route "${route}": Next.js encountered uncached data during the initial render or a navigation.\n\n` + + `\`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\n\n` + + `Ways to fix this:\n` + + ` - Cache the data access with \`"use cache"\`\n` + + ` - Provide a placeholder with \`\` around the data access\n` + + ` - Set \`export const instant = false\` to allow a blocking route\n\n` + + `Learn more: https://nextjs.org/docs/messages/blocking-route` + ) +} + /** * NOTE: Prefer `createRuntimeBodyError` or `createDynamicBodyError`. * Only use this in situations like build-time static validation, where diff --git a/packages/next/src/server/app-render/dynamic-rendering.ts b/packages/next/src/server/app-render/dynamic-rendering.ts index 5fb7bbbdeb2b..e8c699614460 100644 --- a/packages/next/src/server/app-render/dynamic-rendering.ts +++ b/packages/next/src/server/app-render/dynamic-rendering.ts @@ -50,6 +50,8 @@ import { BailoutToCSRError } from '../../shared/lib/lazy-dynamic/bailout-to-csr' import { createRuntimeBodyError, createDynamicBodyError, + createRuntimeBodyErrorInNavigation, + createDynamicBodyErrorInNavigation, createDynamicOrRuntimeBodyError, createRuntimeMetadataError, createDynamicMetadataError, @@ -1026,8 +1028,8 @@ export function trackDynamicHoleInNavigation( const error = addErrorContext( kind === DynamicHoleKind.Runtime - ? createRuntimeBodyError(workStore.route) - : createDynamicBodyError(workStore.route), + ? createRuntimeBodyErrorInNavigation(workStore.route) + : createDynamicBodyErrorInNavigation(workStore.route), componentStack, effectiveCreateInstantStack ) diff --git a/packages/next/src/server/config.ts b/packages/next/src/server/config.ts index 0fc91649ce85..2c4827f7abdd 100644 --- a/packages/next/src/server/config.ts +++ b/packages/next/src/server/config.ts @@ -1590,7 +1590,8 @@ function finalizeConfig(config: NextConfigComplete): NextConfigComplete { async function applyModifyConfig( config: NextConfigComplete, phase: PHASE_TYPE, - silent: boolean + silent: boolean, + dir: string ): Promise { // we always call modify config and phase can be used to only // modify for specific times @@ -1607,6 +1608,7 @@ async function applyModifyConfig( config = await adapterMod.modifyConfig(config, { phase, nextVersion: process.env.__NEXT_VERSION as string, + projectDir: dir, }) } } @@ -1779,7 +1781,8 @@ export default async function loadConfig( phase ), phase, - silent + silent, + dir ) ) @@ -1802,6 +1805,7 @@ export default async function loadConfig( configFileName = basename(path) let userConfigModule: any + let loadedConfig: NextConfig try { const envBefore = Object.assign({}, process.env) @@ -1842,6 +1846,18 @@ export default async function loadConfig( return userConfigModule } + + // `normalizeConfig` invokes the user's exported config function (or + // awaits its returned promise) if it is one. Errors thrown from that + // call belong to the same "failed to load config" category as parse + // errors from `import()` above, so we keep them inside this try/catch + // to attach the same framing message. + loadedConfig = Object.freeze( + (await normalizeConfig( + phase, + interopDefault(userConfigModule) + )) as NextConfig + ) } catch (err) { // Capture the error for MCP tool reporting NextInstanceErrorState.nextConfig.push(err) @@ -1853,13 +1869,6 @@ export default async function loadConfig( throw err } - const loadedConfig = Object.freeze( - (await normalizeConfig( - phase, - interopDefault(userConfigModule) - )) as NextConfig - ) - if (loadedConfig.experimental) { for (const name of Object.keys( loadedConfig.experimental @@ -1977,7 +1986,7 @@ export default async function loadConfig( ) const finalConfig = finalizeConfig( - await applyModifyConfig(completeConfig, phase, silent) + await applyModifyConfig(completeConfig, phase, silent, dir) ) // Cache the final result @@ -2036,7 +2045,7 @@ export default async function loadConfig( setHttpClientAndAgentOptions(completeConfig) const finalConfig = finalizeConfig( - await applyModifyConfig(completeConfig, phase, silent) + await applyModifyConfig(completeConfig, phase, silent, dir) ) // Cache the default config result diff --git a/test/e2e/app-dir/instant-validation-build/instant-validation-build.test.ts b/test/e2e/app-dir/instant-validation-build/instant-validation-build.test.ts index b776555f0046..13f2f996118a 100644 --- a/test/e2e/app-dir/instant-validation-build/instant-validation-build.test.ts +++ b/test/e2e/app-dir/instant-validation-build/instant-validation-build.test.ts @@ -63,9 +63,9 @@ describe('instant-validation-build', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/invalid-missing-suspense-around-runtime": Next.js encountered uncached data during the initial render. + "Error: Route "/invalid-missing-suspense-around-runtime": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` diff --git a/test/e2e/app-dir/instant-validation-causes/instant-validation-causes.test.ts b/test/e2e/app-dir/instant-validation-causes/instant-validation-causes.test.ts index d79b24574e98..1a9eb517f614 100644 --- a/test/e2e/app-dir/instant-validation-causes/instant-validation-causes.test.ts +++ b/test/e2e/app-dir/instant-validation-causes/instant-validation-causes.test.ts @@ -105,8 +105,8 @@ describe('instant validation causes', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/named-export/page.tsx (7:16) @ Page @@ -136,8 +136,8 @@ describe('instant validation causes', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/aliased-export/page.tsx (7:16) @ Page @@ -167,8 +167,8 @@ describe('instant validation causes', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/reexport/page.tsx (6:16) @ Page @@ -201,8 +201,8 @@ describe('instant validation causes', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/indirect-export/page.tsx (8:16) @ Page diff --git a/test/e2e/app-dir/instant-validation-level-error/instant-validation-level-error.test.ts b/test/e2e/app-dir/instant-validation-level-error/instant-validation-level-error.test.ts index 84417eae91f7..ac346f83eb96 100644 --- a/test/e2e/app-dir/instant-validation-level-error/instant-validation-level-error.test.ts +++ b/test/e2e/app-dir/instant-validation-level-error/instant-validation-level-error.test.ts @@ -60,8 +60,8 @@ describe('instant validation - level error', () => { const browser = await next.browser('/bare') await expect(browser).toDisplayCollapsedRedbox(` { - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/bare/page.tsx (11:19) @ Page @@ -90,8 +90,8 @@ describe('instant validation - level error', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/explicit-error/page.tsx (11:19) @ Page @@ -120,8 +120,8 @@ describe('instant validation - level error', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/explicit-true/page.tsx (12:19) @ Page @@ -150,8 +150,8 @@ describe('instant validation - level error', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/explicit-warning/page.tsx (11:19) @ Page @@ -177,8 +177,8 @@ describe('instant validation - level error', () => { const browser = await next.browser('/layered') await expect(browser).toDisplayCollapsedRedbox(` { - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/layered/page.tsx (8:19) @ Page @@ -197,9 +197,9 @@ describe('instant validation - level error', () => { const result = await prerender('/bare') expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/bare": Next.js encountered uncached data during the initial render. + "Error: Route "/bare": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -223,9 +223,9 @@ describe('instant validation - level error', () => { const result = await prerender('/explicit-error') expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/explicit-error": Next.js encountered uncached data during the initial render. + "Error: Route "/explicit-error": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -249,9 +249,9 @@ describe('instant validation - level error', () => { const result = await prerender('/explicit-true') expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/explicit-true": Next.js encountered uncached data during the initial render. + "Error: Route "/explicit-true": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -288,9 +288,9 @@ describe('instant validation - level error', () => { const result = await prerender('/layered') expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/layered": Next.js encountered uncached data during the initial render. + "Error: Route "/layered": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` diff --git a/test/e2e/app-dir/instant-validation-level-manual-error/instant-validation-level-manual-error.test.ts b/test/e2e/app-dir/instant-validation-level-manual-error/instant-validation-level-manual-error.test.ts index 1b78c6d380b2..74f9e9fdb444 100644 --- a/test/e2e/app-dir/instant-validation-level-manual-error/instant-validation-level-manual-error.test.ts +++ b/test/e2e/app-dir/instant-validation-level-manual-error/instant-validation-level-manual-error.test.ts @@ -79,8 +79,8 @@ describe('instant validation - level manual-error', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/explicit-error/page.tsx (11:19) @ Page @@ -109,8 +109,8 @@ describe('instant validation - level manual-error', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/explicit-true/page.tsx (12:19) @ Page @@ -139,8 +139,8 @@ describe('instant validation - level manual-error', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/explicit-warning/page.tsx (11:19) @ Page @@ -180,9 +180,9 @@ describe('instant validation - level manual-error', () => { const result = await prerender('/explicit-error') expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/explicit-error": Next.js encountered uncached data during the initial render. + "Error: Route "/explicit-error": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -206,9 +206,9 @@ describe('instant validation - level manual-error', () => { const result = await prerender('/explicit-true') expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/explicit-true": Next.js encountered uncached data during the initial render. + "Error: Route "/explicit-true": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` diff --git a/test/e2e/app-dir/instant-validation-level-manual-warning/instant-validation-level-manual-warning.test.ts b/test/e2e/app-dir/instant-validation-level-manual-warning/instant-validation-level-manual-warning.test.ts index 3f0e9e88a20f..7ca9596bed3a 100644 --- a/test/e2e/app-dir/instant-validation-level-manual-warning/instant-validation-level-manual-warning.test.ts +++ b/test/e2e/app-dir/instant-validation-level-manual-warning/instant-validation-level-manual-warning.test.ts @@ -93,8 +93,8 @@ describe('instant validation - level manual-warning', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/with-root-suspense/explicit-error/page.tsx (11:19) @ Page @@ -125,8 +125,8 @@ describe('instant validation - level manual-warning', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/with-root-suspense/explicit-true/page.tsx (10:19) @ Page @@ -157,8 +157,8 @@ describe('instant validation - level manual-warning', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/with-root-suspense/explicit-warning/page.tsx (9:19) @ Page @@ -192,9 +192,9 @@ describe('instant validation - level manual-warning', () => { const result = await prerender('/with-root-suspense/explicit-error') expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/with-root-suspense/explicit-error": Next.js encountered uncached data during the initial render. + "Error: Route "/with-root-suspense/explicit-error": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` diff --git a/test/e2e/app-dir/instant-validation-level-warning/instant-validation-level-warning.test.ts b/test/e2e/app-dir/instant-validation-level-warning/instant-validation-level-warning.test.ts index f5cbb87854cf..d3db682bad6a 100644 --- a/test/e2e/app-dir/instant-validation-level-warning/instant-validation-level-warning.test.ts +++ b/test/e2e/app-dir/instant-validation-level-warning/instant-validation-level-warning.test.ts @@ -60,8 +60,8 @@ describe('instant validation - level warning', () => { const browser = await next.browser('/bare') await expect(browser).toDisplayCollapsedRedbox(` { - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/bare/page.tsx (10:19) @ Page @@ -90,8 +90,8 @@ describe('instant validation - level warning', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/explicit-error/page.tsx (10:19) @ Page @@ -120,8 +120,8 @@ describe('instant validation - level warning', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/explicit-true/page.tsx (11:19) @ Page @@ -150,8 +150,8 @@ describe('instant validation - level warning', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/explicit-warning/page.tsx (11:19) @ Page @@ -177,8 +177,8 @@ describe('instant validation - level warning', () => { const browser = await next.browser('/layered') await expect(browser).toDisplayCollapsedRedbox(` { - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/layered/page.tsx (8:19) @ Page @@ -202,9 +202,9 @@ describe('instant validation - level warning', () => { const result = await prerender('/explicit-error') expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/explicit-error": Next.js encountered uncached data during the initial render. + "Error: Route "/explicit-error": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` diff --git a/test/e2e/app-dir/instant-validation/instant-validation-parallel-slots.test.ts b/test/e2e/app-dir/instant-validation/instant-validation-parallel-slots.test.ts index 9fb825531120..cefa1e09041c 100644 --- a/test/e2e/app-dir/instant-validation/instant-validation-parallel-slots.test.ts +++ b/test/e2e/app-dir/instant-validation/instant-validation-parallel-slots.test.ts @@ -124,8 +124,8 @@ describe('instant validation - parallel slot configs', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/parallel/slot-config-only/page.tsx (4:16) @ ChildrenPage @@ -142,9 +142,9 @@ describe('instant validation - parallel slot configs', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/parallel/slot-config-only": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/parallel/slot-config-only": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -184,8 +184,8 @@ describe('instant validation - parallel slot configs', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/parallel/slot-layout-config/page.tsx (4:16) @ ChildrenPage @@ -202,9 +202,9 @@ describe('instant validation - parallel slot configs', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/parallel/slot-layout-config": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/parallel/slot-layout-config": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -244,8 +244,8 @@ describe('instant validation - parallel slot configs', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/parallel/slot-runtime-config/page.tsx (4:16) @ ChildrenPage @@ -262,9 +262,9 @@ describe('instant validation - parallel slot configs', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/parallel/slot-runtime-config": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/parallel/slot-runtime-config": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -306,8 +306,8 @@ describe('instant validation - parallel slot configs', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/parallel/children-config-with-slot/@slot/page.tsx (4:16) @ SlotPage @@ -324,9 +324,9 @@ describe('instant validation - parallel slot configs', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/parallel/children-config-with-slot": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/parallel/children-config-with-slot": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -368,8 +368,8 @@ describe('instant validation - parallel slot configs', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/parallel/fork-layout-config-with-slot/@slot/page.tsx (4:16) @ SlotPage @@ -392,8 +392,8 @@ describe('instant validation - parallel slot configs', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/parallel/fork-layout-config-with-slot/page.tsx (4:16) @ ChildrenPage @@ -411,9 +411,9 @@ describe('instant validation - parallel slot configs', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/parallel/fork-layout-config-with-slot": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/parallel/fork-layout-config-with-slot": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -425,9 +425,9 @@ describe('instant validation - parallel slot configs', () => { at body () at html () at a () - Error: Route "/suspense-in-root/parallel/fork-layout-config-with-slot": Next.js encountered runtime data during the initial render. + Error: Route "/suspense-in-root/parallel/fork-layout-config-with-slot": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -535,8 +535,8 @@ describe('instant validation - parallel slot configs', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/parallel/conditional-breadcrumbs/show-both/@breadcrumbs/blocked/page.tsx (3:16) @ BreadcrumbsPage @@ -551,9 +551,9 @@ describe('instant validation - parallel slot configs', () => { const result = await prerender(href) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/parallel/conditional-breadcrumbs/show-both/blocked": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/parallel/conditional-breadcrumbs/show-both/blocked": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -583,7 +583,7 @@ describe('instant validation - parallel slot configs', () => { const browser = await navigateTo(href) await expect(browser).toDisplayCollapsedRedbox(` { - "code": "E1246", + "code": "E1248", "description": "Could not validate instant UI because an expected segment was not rendered. Unrendered segment: @@ -650,8 +650,8 @@ describe('instant validation - parallel slot configs', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/parallel/conditional-breadcrumbs/show-only-breadcrumbs/@breadcrumbs/blocked/page.tsx (3:16) @ BreadcrumbsPage @@ -666,9 +666,9 @@ describe('instant validation - parallel slot configs', () => { const result = await prerender(href) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/parallel/conditional-breadcrumbs/show-only-breadcrumbs/blocked": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/parallel/conditional-breadcrumbs/show-only-breadcrumbs/blocked": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access diff --git a/test/e2e/app-dir/instant-validation/instant-validation.test.ts b/test/e2e/app-dir/instant-validation/instant-validation.test.ts index d155428d591b..9b3def2e15e1 100644 --- a/test/e2e/app-dir/instant-validation/instant-validation.test.ts +++ b/test/e2e/app-dir/instant-validation/instant-validation.test.ts @@ -180,8 +180,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/missing-suspense-around-runtime/page.tsx (6:16) @ Page @@ -198,9 +198,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/missing-suspense-around-runtime": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/missing-suspense-around-runtime": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -240,8 +240,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/missing-suspense-around-dynamic/page.tsx (6:19) @ Page @@ -258,9 +258,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/missing-suspense-around-dynamic": Next.js encountered uncached data during the initial render. + "Error: Route "/suspense-in-root/static/missing-suspense-around-dynamic": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -300,8 +300,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/runtime/missing-suspense-around-dynamic/page.tsx (23:19) @ Dynamic @@ -319,9 +319,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/runtime/missing-suspense-around-dynamic": Next.js encountered uncached data during the initial render. + "Error: Route "/suspense-in-root/runtime/missing-suspense-around-dynamic": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -363,8 +363,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/missing-suspense-around-dynamic-layout/layout.tsx (7:16) @ Layout @@ -381,9 +381,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/missing-suspense-around-dynamic-layout": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/missing-suspense-around-dynamic-layout": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -423,8 +423,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/runtime/missing-suspense-around-dynamic-layout/layout.tsx (8:19) @ Layout @@ -441,9 +441,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/runtime/missing-suspense-around-dynamic-layout": Next.js encountered uncached data during the initial render. + "Error: Route "/suspense-in-root/runtime/missing-suspense-around-dynamic-layout": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -486,8 +486,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/missing-suspense-around-params/[param]/page.tsx (20:21) @ Runtime @@ -534,8 +534,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/missing-suspense-around-search-params/page.tsx (7:18) @ Page @@ -552,9 +552,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/missing-suspense-around-search-params": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/missing-suspense-around-search-params": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -629,8 +629,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/suspense-too-high/page.tsx (6:16) @ Page @@ -647,9 +647,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/suspense-too-high": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/suspense-too-high": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -692,8 +692,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/runtime/suspense-too-high/page.tsx (24:19) @ Dynamic @@ -711,9 +711,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/runtime/suspense-too-high": Next.js encountered uncached data during the initial render. + "Error: Route "/suspense-in-root/runtime/suspense-too-high": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -1231,8 +1231,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/invalid-loading-above-route-group/(group)/page.tsx (34:19) @ Dynamic @@ -1250,9 +1250,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/invalid-loading-above-route-group": Next.js encountered uncached data during the initial render. + "Error: Route "/suspense-in-root/static/invalid-loading-above-route-group": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -1295,8 +1295,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/invalid-dynamic-layout-with-loading/layout.tsx (24:19) @ Dynamic @@ -1314,9 +1314,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/invalid-dynamic-layout-with-loading": Next.js encountered uncached data during the initial render. + "Error: Route "/suspense-in-root/static/invalid-dynamic-layout-with-loading": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -1372,8 +1372,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/blocking-layout/missing-suspense-around-dynamic/page.tsx (6:16) @ Page @@ -1390,9 +1390,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/blocking-layout/missing-suspense-around-dynamic": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/blocking-layout/missing-suspense-around-dynamic": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -1460,8 +1460,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/invalid-blocking-inside-static/page.tsx (6:16) @ BlockingPage @@ -1478,9 +1478,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/invalid-blocking-inside-static": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/invalid-blocking-inside-static": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -1521,8 +1521,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/runtime/invalid-blocking-inside-runtime/page.tsx (6:19) @ BlockingPage @@ -1539,9 +1539,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/runtime/invalid-blocking-inside-runtime": Next.js encountered uncached data during the initial render. + "Error: Route "/suspense-in-root/runtime/invalid-blocking-inside-runtime": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -1585,8 +1585,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/missing-suspense-in-parallel-route/@slot/page.tsx (4:16) @ IndexSlot @@ -1603,9 +1603,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/missing-suspense-in-parallel-route": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/missing-suspense-in-parallel-route": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -1647,8 +1647,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/missing-suspense-in-parallel-route/@slot/foo/page.tsx (4:16) @ FooSlot @@ -1665,9 +1665,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/missing-suspense-in-parallel-route/foo": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/missing-suspense-in-parallel-route/foo": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -1709,8 +1709,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/missing-suspense-in-parallel-route/@slot/default.tsx (4:16) @ DefaultSlot @@ -1727,9 +1727,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/missing-suspense-in-parallel-route/bar": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/missing-suspense-in-parallel-route/bar": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -2580,8 +2580,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/route-group-config-only/(group)/page.tsx (4:16) @ Page @@ -2598,9 +2598,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/route-group-config-only": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/route-group-config-only": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -2641,8 +2641,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/route-group-config-and-segment-config/(group)/page.tsx (4:16) @ Page @@ -2659,9 +2659,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/route-group-config-and-segment-config": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/route-group-config-and-segment-config": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -2703,8 +2703,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/route-group-segment-config-only/(group)/page.tsx (4:16) @ Page @@ -2721,9 +2721,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/route-group-segment-config-only": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/route-group-segment-config-only": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -2765,8 +2765,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/route-group-config-with-deeper-segment/(group)/inner/page.tsx (4:16) @ Page @@ -2783,9 +2783,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/route-group-config-with-deeper-segment/inner": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/route-group-config-with-deeper-segment/inner": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -2827,8 +2827,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/route-group-deeper-segment-config/(group)/inner/page.tsx (4:16) @ Page @@ -2845,9 +2845,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/route-group-deeper-segment-config/inner": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/route-group-deeper-segment-config/inner": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -2896,8 +2896,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/route-group-shared-boundary/(outer)/(inner)/layout.tsx (13:16) @ InnerLayout @@ -2914,9 +2914,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/route-group-shared-boundary": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/route-group-shared-boundary": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -2972,8 +2972,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/parallel-group-depths-deep-slot-hole/@slot/(g1)/(g2)/(g3)/layout.tsx (7:16) @ G3Layout @@ -2990,9 +2990,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/parallel-group-depths-deep-slot-hole": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/parallel-group-depths-deep-slot-hole": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -3042,8 +3042,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/parallel-group-depths-shallow-slot-hole/(b1)/(b2)/layout.tsx (5:16) @ B2Layout @@ -3060,9 +3060,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/parallel-group-depths-shallow-slot-hole": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/parallel-group-depths-shallow-slot-hole": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -3113,8 +3113,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/runtime/static-layout-above-runtime-config/layout.tsx (15:16) @ StaticLayout @@ -3131,9 +3131,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/runtime/static-layout-above-runtime-config/inner": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/runtime/static-layout-above-runtime-config/inner": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -3181,8 +3181,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/config-depth-preference/@slot/[...catchall]/page.tsx (8:16) @ CatchallSlotPage @@ -3232,8 +3232,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/config-depth-preference-slot-wins/@slot/[...catchall]/page.tsx (7:16) @ CatchallSlotPage @@ -3250,9 +3250,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/config-depth-preference-slot-wins/deeper/[...rest]": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/config-depth-preference-slot-wins/deeper/[...rest]": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -3296,8 +3296,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/config-children-preferred/@slot/page.tsx (7:16) @ SlotPage @@ -3314,9 +3314,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/static/config-children-preferred": Next.js encountered runtime data during the initial render. + "Error: Route "/suspense-in-root/static/config-children-preferred": Next.js encountered runtime data during the initial render or a navigation. - \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Provide a placeholder with \`\` around the data access @@ -3361,8 +3361,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1221", - "description": "Next.js encountered runtime data during the initial render.", + "code": "E1251", + "description": "Next.js encountered runtime data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/static/cross-slot-blocking/@slot/[...catchall]/page.tsx (8:16) @ CatchallSlotPage @@ -3412,7 +3412,7 @@ describe('instant validation', () => { ) await expect(browser).toDisplayCollapsedRedbox(` { - "code": "E1246", + "code": "E1248", "description": "Could not validate instant UI because an expected segment was not rendered. Unrendered segment: @@ -3476,7 +3476,7 @@ describe('instant validation', () => { ) await expect(browser).toDisplayCollapsedRedbox(` { - "code": "E1246", + "code": "E1248", "description": "Could not validate instant UI because an expected segment was not rendered. Unrendered segment: @@ -3538,7 +3538,7 @@ describe('instant validation', () => { ) await expect(browser).toDisplayCollapsedRedbox(` { - "code": "E1246", + "code": "E1248", "description": "Could not validate instant UI because an expected segment was not rendered. Unrendered segments: @@ -3646,9 +3646,9 @@ describe('instant validation', () => { ) expect(extractBuildValidationError(result.cliOutput)) .toMatchInlineSnapshot(` - "Error: Route "/suspense-in-root/disable-validation/disable-dev": Next.js encountered uncached data during the initial render. + "Error: Route "/suspense-in-root/disable-validation/disable-dev": Next.js encountered uncached data during the initial render or a navigation. - \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered, blocking navigation and leading to a slower user experience. + \`fetch(...)\` or \`connection()\` accessed outside of \`\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience. Ways to fix this: - Cache the data access with \`"use cache"\` @@ -3688,8 +3688,8 @@ describe('instant validation', () => { ], }, ], - "code": "E1220", - "description": "Next.js encountered uncached data during the initial render.", + "code": "E1249", + "description": "Next.js encountered uncached data during a navigation.", "environmentLabel": "Server", "label": "Instant", "source": "app/suspense-in-root/disable-validation/disable-build/page.tsx (9:19) @ Page diff --git a/test/production/adapter-config/adapter-config-export.test.ts b/test/production/adapter-config/adapter-config-export.test.ts index ddc75b5242fe..640f170741f1 100644 --- a/test/production/adapter-config/adapter-config-export.test.ts +++ b/test/production/adapter-config/adapter-config-export.test.ts @@ -55,6 +55,7 @@ describe('adapter-config export', () => { } expect(ctx.nextVersion).toBe(nextVersion) + expect(ctx.projectDir).toBe(next.testDir) expect(config?.basePath).toBe('/docs') const combinedRouteOutputs = [ diff --git a/test/production/adapter-config/adapter-config.test.ts b/test/production/adapter-config/adapter-config.test.ts index eedfb9506ac8..c93763880263 100644 --- a/test/production/adapter-config/adapter-config.test.ts +++ b/test/production/adapter-config/adapter-config.test.ts @@ -43,6 +43,7 @@ describe('adapter-config', () => { } expect(ctx.nextVersion).toBe(nextVersion) + expect(ctx.projectDir).toBe(next.testDir) expect(config?.basePath).toBe('/docs') const combinedRouteOutputs = [ diff --git a/test/production/config-evaluation-error/config-evaluation-error.test.ts b/test/production/config-evaluation-error/config-evaluation-error.test.ts new file mode 100644 index 000000000000..57a78e74d2cd --- /dev/null +++ b/test/production/config-evaluation-error/config-evaluation-error.test.ts @@ -0,0 +1,68 @@ +import { nextTestSetup } from 'e2e-utils' + +describe('next.config evaluation error', () => { + describe('production mode', () => { + const { next, skipped } = nextTestSetup({ + files: __dirname, + skipStart: true, + skipDeployment: true, + }) + if (skipped) return + + async function buildAndGetOutput(): Promise { + const start = next.cliOutput.length + await next.build() + return next.cliOutput.slice(start) + } + + it('should report a helpful error when the config function throws synchronously', async () => { + await next.patchFile( + 'next.config.js', + ` + module.exports = () => { + return { foo: new Uint8Array(5_000_000_000) } + } + ` + ) + const output = await buildAndGetOutput() + + expect(output).toContain('Invalid typed array length') + expect(output).toContain( + 'Failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error' + ) + }) + + it('should report a helpful error when the config module throws at the top level', async () => { + await next.patchFile( + 'next.config.js', + ` + const buf = new Uint8Array(5_000_000_000) + module.exports = { foo: buf } + ` + ) + const output = await buildAndGetOutput() + + expect(output).toContain('Invalid typed array length') + expect(output).toContain( + 'Failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error' + ) + }) + + it('should report a helpful error when the config function rejects', async () => { + await next.patchFile( + 'next.config.js', + ` + module.exports = async () => { + throw new Error('boom from async config plugin') + } + ` + ) + const output = await buildAndGetOutput() + + expect(output).toContain('boom from async config plugin') + expect(output).toContain( + 'Failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error' + ) + }) + }) +}) diff --git a/test/production/config-evaluation-error/pages/index.js b/test/production/config-evaluation-error/pages/index.js new file mode 100644 index 000000000000..821fdd14d097 --- /dev/null +++ b/test/production/config-evaluation-error/pages/index.js @@ -0,0 +1,3 @@ +export default function Page(props) { + return

index page

+}