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:
Navigation Boundaries form the core runtime error-interception and fallback mechanism in Next.js App Router. During client-side navigation, server rendering, or component tree execution, React rendering can be interrupted by explicit signals thrown from user code or unhandled exceptions. Instead of letting these runtime failures crash the entire React root, Next.js intercepts specific router control signals and HTTP access errors (notFound(), forbidden(), unauthorized(), and redirect()) via specialized React error boundaries placed around route segments.
Sources: packages/next/src/client/components/http-access-fallback/error-boundary.tsx:1-182
This subsystem solves the problem of granular recovery: when an error or access interruption occurs in a leaf segment, it should not dismantle parent layouts or root chrome unless explicitly required. Sources: packages/next/src/client/components/error-boundary.tsx:1-182
The key design decisions embody throwing structured Error objects with specific digest signatures (such as NEXT_HTTP_ERROR_FALLBACK;404), inspecting these errors via isNextRouterError, and bubbling unhandled router signals up to parent segments while catching general JavaScript exceptions in component-level ErrorBoundary or catchError handlers.
Sources: packages/next/src/client/components/redirect-boundary.tsx:1-87
Next.js categorizes thrown routing exceptions to differentiate expected navigation interruptions from unexpected runtime application bugs. Sources: packages/next/src/client/components/is-next-router-error.ts:1-17
The helper function isNextRouterError evaluates whether an unknown thrown value is either a redirect error or an HTTP access fallback error.
Sources: packages/next/src/client/components/is-next-router-error.ts:1-17
export function isNextRouterError(
error: unknown
): error is RedirectError | HTTPAccessFallbackError {
return isRedirectError(error) || isHTTPAccessFallbackError(error)
}HTTP access errors are identified via a prefixed digest string property on standard JavaScript Error instances.
Sources: packages/next/src/client/components/http-access-fallback/http-access-fallback.ts:1-62
The prefix constant HTTP_ERROR_FALLBACK_ERROR_CODE is set to 'NEXT_HTTP_ERROR_FALLBACK', followed by a semicolon and the HTTP status code.
Sources: packages/next/src/client/components/http-access-fallback/http-access-fallback.ts:1-62
HTTPAccessFallbackBoundary)The HTTPAccessFallbackBoundary and its underlying stateful component HTTPAccessFallbackErrorBoundary handle HTTP access errors such as 404 Not Found, 403 Forbidden, and 401 Unauthorized.
Sources: packages/next/src/client/components/http-access-fallback/error-boundary.tsx:1-182
When notFound(), forbidden(), or unauthorized() is invoked in a Server Component, Route Handler, or Server Action, it interrupts rendering by throwing a digested error.
Sources: packages/next/src/client/components/http-access-fallback/error-boundary.tsx:1-182
HTTPAccessFallbackErrorBoundary catches this error in getDerivedStateFromError:
Sources: packages/next/src/client/components/http-access-fallback/error-boundary.tsx:1-182
static getDerivedStateFromError(error: unknown) {
if (isHTTPAccessFallbackError(error)) {
const httpStatus = getAccessFallbackHTTPStatus(error)
return {
triggeredStatus: httpStatus,
}
}
// Re-throw if error is not for 404
throw error
}During render execution, if triggeredStatus is set and matches an available fallback component prop (notFound, forbidden, or unauthorized), the boundary injects a <meta name="robots" content="noindex" /> tag, appends development-mode metadata tags if applicable, and renders the corresponding fallback component.
Sources: packages/next/src/client/components/http-access-fallback/error-boundary.tsx:1-182
Note
Navigation updates automatically reset the error boundary state. getDerivedStateFromProps compares props.pathname to state.previousPathname; if a navigation has occurred (props.pathname !== state.previousPathname), triggeredStatus is reset to undefined.
Sources: packages/next/src/client/components/http-access-fallback/error-boundary.tsx:1-182
RedirectBoundary)Redirect operations initiated by redirect() or permanentRedirect() throw a specialized redirect error containing target URL and redirect type metadata (push or replace).
Sources: packages/next/src/client/components/redirect-boundary.tsx:1-87
The RedirectBoundary component intercepts these errors to execute client-side navigation transitions without requiring full page reloads.
Sources: packages/next/src/client/components/redirect-boundary.tsx:1-87
The execution sequence is managed through RedirectErrorBoundary and HandleRedirect:
Sources: packages/next/src/client/components/redirect-boundary.tsx:1-87
If an error has already been marked as handled ('handled' in error), RedirectErrorBoundary catches the error solely to trigger a subtree remount without executing duplicate router navigation commands.
Sources: packages/next/src/client/components/redirect-boundary.tsx:1-87
ErrorBoundary and catchError)General runtime errors thrown during React rendering are caught by ErrorBoundary (backed by ErrorBoundaryHandler) or the granular HOC wrapper catchError.
Sources: packages/next/src/client/components/error-boundary.tsx:1-182, packages/next/src/client/components/catch-error.tsx:1-221
Both components implement guard logic in getDerivedStateFromError to inspect incoming exceptions:
Sources: packages/next/src/client/components/error-boundary.tsx:1-182
static getDerivedStateFromError(
thrownValue: unknown
): Partial<ErrorBoundaryHandlerState> {
if (isNextRouterError(thrownValue)) {
// Re-throw if an expected internal Next.js router error occurs
// this means it should be handled by a different boundary (such as a NotFound boundary in a parent segment)
throw thrownValue
}
return { error: { thrownValue } }
}Important
The guard if (isNextRouterError(thrownValue)) { throw thrownValue } is critical. It guarantees that router navigation signals (redirect, notFound, forbidden, unauthorized) are never swallowed by generic React error components, allowing them to propagate past component error boundaries straight to their respective HTTP or redirect boundary handlers.
Sources: packages/next/src/client/components/error-boundary.tsx:1-182
When a non-router runtime error is caught, ErrorBoundaryHandler renders errorStyles, errorScripts, and the supplied errorComponent, providing an ErrorInfo object containing error, reset, and retry functions.
Sources: packages/next/src/client/components/error-boundary.tsx:1-182
Calling retry() triggers an asynchronous React transition that calls router.refresh() alongside resetting local error state.
Sources: packages/next/src/client/components/error-boundary.tsx:1-182
When an exception or rejection occurs while a navigation operation is pending, Next.js provides robust failure recovery via handleHardNavError and useNavFailureHandler.
Sources: packages/next/src/client/components/nav-failure-handler.ts:1-47
export function handleHardNavError(error: unknown): boolean {
if (
typeof window !== 'undefined' &&
window.next.__pendingUrl &&
createHrefFromUrl(new URL(window.location.href)) !==
createHrefFromUrl(window.next.__pendingUrl)
) {
console.error(
`Error occurred during navigation, falling back to hard navigation`,
error
)
window.location.href = window.next.__pendingUrl.toString()
return true
}
return false
}The validation check createHrefFromUrl(new URL(window.location.href)) !== createHrefFromUrl(window.next.__pendingUrl) ensures that a hard navigation fallback is only triggered if the current URL differs from the pending navigation target.
Sources: packages/next/src/client/components/nav-failure-handler.ts:1-47
When triggered, it logs the navigation error and assigns window.location.href to force a full-document reload to recover to a consistent state.
Sources: packages/next/src/client/components/nav-failure-handler.ts:1-47
During local development (NODE_ENV !== 'production'), navigation boundaries integrate with Next.js DevTools and segment explorer overlays to simulate and debug boundary states.
Sources: packages/next/src/next-devtools/userspace/app/segment-explorer-node.tsx:1-166
The SegmentStateProvider and SegmentBoundaryTriggerNode allow developers to interactively toggle segment boundary types.
Sources: packages/next/src/next-devtools/userspace/app/segment-explorer-node.tsx:1-166
Furthermore, AppDevOverlayErrorBoundary intercepts runtime errors, tracks occurrence via RuntimeErrorHandler.hadRuntimeError = true, and invokes dispatcher.openErrorOverlay() to present detailed error frames.
Sources: packages/next/src/next-devtools/userspace/app/app-dev-overlay-error-boundary.tsx:1-104
Sources: packages/next/src/client/components/http-access-fallback/http-access-fallback.ts:1-62, packages/next/src/client/components/error-boundary.tsx:1-182, packages/next/src/client/components/nav-failure-handler.ts:1-47