Architecture Overview
Server Runtime
Rendering Pipeline
Client Navigation
Caching and Export
Development Tools
Build and Configuration
Ecosystem Packages
Testing Infrastructure
How It Works
The following files were used as context for generating this wiki page:
Instant validation provides a compile-time and development-time verification mechanism for Next.js App Router applications to ensure that routes configured with instant navigation or static optimization requirements satisfy their expected parameter contracts, layout constraints, and boundary structures. By evaluating loader trees, simulating request contexts with synthetic samples, and tracking dynamic data access across server and client component boundaries, the system catches misconfigurations and missing inputs early, preventing runtime rendering failures and static generation bailouts.
Sources: packages/next/src/server/app-render/instant-validation/instant-samples.ts:1-74, packages/next/src/server/app-render/app-render.tsx:6533-6666, packages/next/src/server/app-render/instant-validation/instant-validation.tsx:1-46, packages/next/src/server/app-render/instant-validation/instant-config.tsx:1-51
Analyzing loader trees determines instant validation eligibility and blocking rules across segment configurations in Next.js. The system inspects layouts and pages recursively to evaluate validation levels, runtime prefetch capabilities, and whether specific segments are permitted to block navigation or require static shells.
The loader tree evaluation engine follows a recursive traversal pattern across route segments, checking module exports and parallel route slots. The execution call chain operates through specific internal functions:
anySegmentNeedsInstantValidation() — Serves as the top-level orchestrator retrieving validation settings from the active WorkStore.visit() — Recursively traverses the LoaderTree to extract layout or page modules via getLayoutOrPageModule().isImplicitValidationSegment() — Determines if unconfigured page or default segments qualify for implicit validation under non-manual default levels.isFrameworkErrorRoute() — Evaluates whether a route corresponds to framework-synthesized error (_not-found or _global-error) entry points to exclude them from default validation.Sources: packages/next/src/server/app-render/instant-validation/instant-config.tsx:28-51, packages/next/src/server/app-render/instant-validation/instant-config.tsx:126-224
Validation behavior is governed by configuration properties defined on segment configs and global work stores. The system maps validation options to internal execution flags and validation thresholds.
Sources: packages/next/src/server/app-render/instant-validation/instant-config.tsx:53-77, packages/next/src/server/app-render/instant-validation/instant-config.tsx:111-234
Warning
Setting unstable_disableValidation: true on any segment config short-circuits the recursive visitor and completely aborts instant validation for the entire route tree, ignoring all other explicit opt-ins or implicit rules.
When resolving instant configuration samples for a page, inner segments override outer segments without performing merge logic. The resolveInstantConfigSamplesForPage function walks child trees along the children parallel route slot to collect sample definitions.
Sources: packages/next/src/server/app-render/instant-validation/instant-config.tsx:46-51, packages/next/src/server/app-render/instant-validation/instant-config.tsx:236-275
Synthetic sample parameters, cookies, and headers are generated and tracked during instant validation to simulate runtime access conditions. When dynamic values like cookies or route parameters are accessed without being declared in the configured sample data, the subsystem logs and throws errors using specialized tracking mechanisms.
The sample tracking infrastructure inspects the active workUnitAsyncStorage store to locate and record missing sample access errors into an InstantValidationSampleTracking container.
The validation tracking call chain operates through specific internal functions:
getExpectedSampleTracking() → retrieves the active store from workUnitAsyncStorage and branches on workUnitStore.type (accepting 'request' or 'validation-client') → extracts validationSampleTracking or throws an InvariantError if missing → trackMissingSampleError() pushes the error to missingSampleErrors → trackMissingSampleErrorAndThrow() calls trackMissingSampleError() and then throws the InstantValidationError.
Note
During validation store inspection, store types such as 'cache', 'prerender', and 'generate-static-params' intentionally skip tracking retrieval, whereas any unhandled store type triggers a TypeScript exhaustive check (workUnitStore satisfies never).
Sources: packages/next/src/server/app-render/instant-validation/instant-samples.ts:19-74, packages/next/src/server/app-render/instant-validation/instant-validation-error.ts:1-17
Cookies and search parameters are synthesized from sample configurations to construct proxy-wrapped request state.
export function createCookiesFromSample(
sampleCookies: InstantSample['cookies'],
route: string
): ReadonlyRequestCookies {
const declaredNames = new Set<string>()
const cookies = new RequestCookies(new Headers())
if (sampleCookies) {
for (const cookie of sampleCookies) {
declaredNames.add(cookie.name)
if (cookie.value !== null) {
cookies.set(cookie.name, cookie.value)
}
}
}
const sealed = RequestCookiesAdapter.seal(cookies)
return new Proxy(sealed, {
get(target, prop, receiver) {
if (prop === 'has') {
const originalMethod = Reflect.get(target, prop, receiver)
const wrappedMethod: typeof originalMethod = function (name) {
if (!declaredNames.has(name)) {
trackMissingSampleErrorAndThrow(
createMissingCookieSampleError(route, name)
)
}
return originalMethod.call(target, name)
}
return wrappedMethod
}
if (prop === 'get') {
// ...
}
}
})
}Search parameters are parsed and built via createURLSearchParamsFromSample, iterating over configured entries and appending arrays or setting string values while ignoring null or undefined entries.
Pathnames are generated from routes and sample parameters using createPathnameFromRouteAndSampleParams. The function splits the route by /, inspects each segment via getSegmentParam, and handles dynamic parameters, catch-all parameters, and static route segments.
Caution
Interception route parameters encountered during sample pathname interpolation immediately throw an InvariantError because validation for interception routes is not implemented.
The assertRootParamInSamples function checks whether a root parameter is defined within sample parameters. If the parameter is missing, it constructs and throws an InstantValidationError via trackMissingSampleErrorAndThrow.
Parameter and search parameter validation bridges client and server component boundaries by inspecting active work unit stores and wrapping underlying parameter collections in exhaustive proxy objects. These proxies check property access against declared keys from unstable_samples configurations, intercepting undeclared lookups to trigger validation errors.
Sources: packages/next/src/server/app-render/instant-validation/instant-samples-client.ts:12-48, packages/next/src/server/request/params.ts:644-657
When validating client components, parameter helpers inspect the current execution environment and construct specialized wrappers. The instrumentation process follows a distinct call chain:
instrumentParamsForClientValidation() queries workAsyncStorage and workUnitAsyncStorage to obtain active stores.workUnitStore.type, matching against the 'validation-client' unit type.validationSamples exist, it extracts declared parameter keys using Object.keys(workUnitStore.validationSamples.params ?? {}).createExhaustiveParamsProxy() with the underlying parameters, declared keys set, and route path to return the restricted parameter proxy.Note
If workUnitStore is not of type 'validation-client' or contains no validation samples, instrumentParamsForClientValidation safely returns the unmodified underlyingParams reference without throwing.
Client validation also verifies complete parameter coverage during specific expression evaluations. The helper function expectCompleteParamsInClientValidation(expression) checks fallback route parameters stored on validation client stores.
Sources: packages/next/src/server/app-render/instant-validation/instant-samples-client.ts:50-87, packages/next/src/server/app-render/instant-validation/instant-samples-client.ts:89-125, packages/next/src/server/request/params.ts:644-657
Client validation boundaries and slot markers manage validation tracking and scope attribution across component trees and parallel layout slots. The implementation uses context providers, specialized boundary components, and namespace objects to ensure rendered validation IDs are tracked and errors are correctly attributed to their originating configuration.
Validation boundaries interact with asynchronous storage to record rendered boundaries and prevent server bundle contamination. The validation boundary execution follows a strict call chain:
InstantValidationBoundary (accessed via NameSpace) invokes getValidationBoundaryTracking() during render.getValidationBoundaryTracking() retrieves the store from workUnitAsyncStorage.getStore().store.type, expecting 'validation-client', and returns store.boundaryState.state.renderedIds.add(id) to register that the boundary with identifier id successfully rendered.Caution
Instant validation boundaries must never appear in browser bundles. Attempting to load boundary-impl.tsx when typeof window !== 'undefined' immediately throws an InvariantError.
When a validation boundary spans multiple parallel slots, SlotMarker uses a cached dynamic component generator to render a marker matching __next_instant_slot_N__. During error handling, resolveInstantStack inspects the component stack using slotMarkerRegex to extract the slot index and retrieve the corresponding configuration stack.
Sources: packages/next/src/server/app-render/dynamic-rendering.ts:780-807, packages/next/src/server/app-render/instant-validation/boundary-impl.tsx:111-138
Tree depth discovery and segment serialization manage the structural traversal of route hierarchies, transforming initial React Server Component (RSC) payloads into segment paths, route trees, and stage-specific chunks.
The segment validation planning phase relies on recursive tree traversal functions to map out RouteTree structures. traverseRootSeedDataSegments extracts root data from an InitialRSCPayload and delegates to traverseCacheNodeSegments, which processes segment nodes and parallel route children.
function traverseRootSeedDataSegments(
initialRSCPayload: InitialRSCPayload,
processSegment: (
segmentPath: SegmentPath,
seedData: CacheNodeSeedData
) => void
) {
const { flightRouterState, seedData } =
getRootDataFromPayload(initialRSCPayload)
const [rootSegment] = flightRouterState
const rootPath = stringifySegment(rootSegment)
return traverseCacheNodeSegments(
rootPath,
flightRouterState,
seedData,
processSegment
)
}Child segment paths are generated via createChildSegmentPath, which checks whether the parallel route key is 'children' or a named parallel slot prefixed with @.
function createChildSegmentPath(
parentPath: SegmentPath,
parallelRouteKey: string,
segment: Segment
): SegmentPath {
const parallelRoutePrefix =
parallelRouteKey === 'children'
? ''
: `@${encodeURIComponent(parallelRouteKey)}/`
return `${parentPath}/${parallelRoutePrefix}${stringifySegment(segment)}` as SegmentPath
}Segments are serialized into SegmentPath strings using stringifySegment, handling string segments by URI encoding them and array segments by encoding their components separated by pipe characters.
function stringifySegment(segment: Segment): SegmentPath {
return (
typeof segment === 'string'
? encodeURIComponent(segment)
: encodeURIComponent(segment[0]) + '|' + segment[1] + '|' + segment[2]
) as SegmentPath
}Note
If a segment key is a page segment (__PAGE__), search parameters may be appended. Consumers reading from the segment cache must ensure search parameters are correctly preserved and appended.
The execution path for data collection and module resolution follows a strict sequence of calls through the rendering and manifests infrastructure:
collectStagedSegmentData initializes the staged chunk streams and triggers processing of component modules and manifests.getServerModuleMap is called during stream operations to resolve module identifiers against the global manifests singleton.getManifestsSingleton retrieves the underlying manifest singleton from globalThis, throwing an InvariantError if it has not been initialized.Sources: packages/next/src/server/app-render/instant-validation/instant-validation.tsx:223-232, packages/next/src/server/app-render/manifests-singleton.ts:319-327
Sources: packages/next/src/server/app-render/instant-validation/instant-validation.tsx:88-107, packages/next/src/server/app-render/instant-validation/instant-validation.tsx:194-210
Sources: packages/next/src/server/app-render/instant-validation/instant-validation.tsx:170-188, packages/next/src/server/app-render/manifests-singleton.ts:19-36
The validation lifecycle manages the execution of asynchronous validation runs, processes validation errors, and handles diagnostics in development and build environments. Build-time validation relies on wrapper utilities that initialize custom contexts and execute sample-based renders.
The build-time validation sequence executes via a specific order of wrapper functions and context initializers:
validateInstantConfigsInBuild acts as the primary entry point, creating test log markers and delegating to run().workAsyncStorage.exit safely exits the outer work store scope before invoking validateInstantConfigsInBuildImpl.validateInstantConfigInBuildWithSample initializes sample URLs, fallback parameters, and mock WorkStore and AppRenderContext structures.workAsyncStorage.run executes the validation render within the isolated sample context.Sources: packages/next/src/server/app-render/app-render.tsx:6533-6593, packages/next/src/server/app-render/app-render.tsx:6668-6785
The InstantValidationError class identifies exhaustive sample validation failures via a fixed string digest value.
Warning
If success evaluates to false during validateInstantConfigsInBuild, the logs record an error and throw a StaticGenBailoutError to immediately halt the static prerender process.