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:
The Dev Error Overlay is Next.js's browser-based diagnostic interface designed to capture, transform, and render runtime errors, unhandled rejections, console errors, and hydration mismatches during development. When an application throws an uncaught error in either the App or Pages router, the overlay intercepts the failure, sanitizes and decorates the error instance, fetches sourcemapped original code locations from the dev server, and presents an interactive stack trace accompanied by a highlighted code frame.
By bridging client-side runtime boundaries with server-side bundler statistics (Webpack and Turbopack), the overlay resolves obfuscated production-style chunks back to original developer source files. It implements specialized handling for React hydration mismatches, error cause chains (error.cause), aggregate errors (AggregateError), and frame ignore-lists (node_modules or anonymous wrappers) to ensure developers focus exclusively on first-party application logic.
The Dev Error Overlay initializes event listeners in the browser environment to intercept global errors, unhandled promise rejections, and intercepted console errors. In the App Router, this setup is bootstrapped via handleGlobalErrors() and patchConsoleError(), while the Pages router mounts PagesDevOverlayBridge.
Sources: packages/next/src/next-devtools/userspace/app/errors/use-error-handler.ts:121-131, packages/next/src/next-devtools/userspace/pages/pages-dev-overlay-setup.tsx:112-126
When an unhandled error or rejection occurs, the event handler wraps or coerces the thrown value into a standard Error instance, attaches React owner stacks if available via setOwnerStackIfAvailable(), and enqueues microtasks to pass the error to the active overlay state handlers without blocking synchronous component rendering.
Sources: packages/next/src/next-devtools/userspace/app/errors/stitched-error.ts:13-28, packages/next/src/next-devtools/userspace/app/errors/use-error-handler.ts:22-57
Note
Events dispatched during module evaluation or early lifecycle phases before React establishes its dispatch function are buffered into a local queue (queue) and replayed via replayQueuedEvents() once maybeDispatch is bound in useInsertionEffect.
Sources: packages/next/src/next-devtools/dev-overlay.browser.tsx:128-142, packages/next/src/next-devtools/dev-overlay.browser.tsx:242-251
// Example usage: Registering and dispatching an unhandled client error
import { handleClientError } from '../next-devtools/userspace/app/errors/use-error-handler'
try {
// Application code that throws a runtime exception
throw new Error('Failed to execute client operation')
} catch (err) {
handleClientError(err as Error)
}Raw stack traces captured in the browser contain obfuscated bundle paths (e.g., _next/static/chunks/...). To map these back to original author-time source files, the Dev Error Overlay transmits raw StackFrame structures to the development server via a POST request to /__nextjs_original-stack-frames.
The server-side overlay middleware (middleware-webpack.ts or middleware-turbopack.ts) inspects the target compilation stats or Turbopack trace engine, resolves line and column positions against applicable source map payloads, and computes original stack frames and code frames.
Sources: packages/next/src/server/dev/middleware-webpack.ts:607-630, packages/next/src/server/dev/middleware-turbopack.ts:364-374
Sources: packages/next/src/next-devtools/shared/stack-frame.ts:97-112, packages/next/src/server/dev/middleware-webpack.ts:611-630
The overlay abstracts bundler differences by routing mapping requests through mapFramesUsingBundler().
clientStats(), serverStats(), and edgeServerStats().nativeTraceSource() or falls back to batchedTraceSource() to query Turbopack's project state directly.Sources: packages/next/src/server/dev/middleware-webpack.ts:477-519, packages/next/src/server/dev/middleware-turbopack.ts:181-284
Warning
If a source map is invalid or malformed, nativeTraceSource and filterStackFrameDEV catch the parsing error and log a warning without re-entering error inspection loops, preventing infinite error recursion.
Sources: packages/next/src/server/dev/middleware-turbopack.ts:186-193, packages/next/src/server/lib/source-maps.ts:144-154
Once original stack frames are resolved, the overlay extracts and renders code snippets via the CodeFrame component. The raw code frame string is formatted by formatCodeFrame(), which strips excess indentation, and tokenized using Anser via groupCodeFrameLines() to support ANSI styling and class-based theming.
Sources: packages/next/src/next-devtools/dev-overlay/components/code-frame/code-frame.tsx:18-28, packages/next/src/next-devtools/dev-overlay/components/code-frame/parse-code-frame.ts:6-41
parseLineNumberFromCodeFrameLine() parses individual line entries to identify line numbers and highlight errored lines (data-nextjs-codeframe-line--errored="true").
Sources: packages/next/src/next-devtools/dev-overlay/components/code-frame/parse-code-frame.ts:82-98
// Example usage: Parsing and rendering code frames directly
import { formatCodeFrame, groupCodeFrameLines } from '../next-devtools/dev-overlay/components/code-frame/parse-code-frame'
const rawCodeFrame = `
1 | function MyComponent() {
> 2 | throw new Error('Boom')
| ^
3 | }
`
const formatted = formatCodeFrame(rawCodeFrame)
const groupedLines = groupCodeFrameLines(formatted)Hydration mismatches between server-rendered HTML and client-side React trees require specialized diagnostics. The overlay captures hydration warnings via storeHydrationErrorStateFromConsoleArgs() in hydration-error-state.ts, distinguishing between React 18 and React 19 warning signatures.
For React 18, generateHydrationDiffReact18() parses component stack traces from console arguments to build an ASCII tree diff highlighting unexpected server vs. client tag structures or text nodes.
// Example usage: Attaching hydration error state to a runtime error
import { attachHydrationErrorState, getSquashedHydrationErrorDetails } from '../next-devtools/userspace/pages/hydration-error-state'
const error = new Error('Hydration failed because the initial UI does not match what was rendered on the server.')
attachHydrationErrorState(error)
const hydrationDetails = getSquashedHydrationErrorDetails(error)When errors chain multiple nested exceptions or aggregate multiple failures, getErrorByType() constructs a structured error tree.
getCauseChain() recursively inspects error.cause up to a maximum depth of 5.getAggregateErrors() unpacks AggregateError instances, processing up to 5 child errors (maxErrors = 5).ErrorOverlayCallStack computes ignoredFramesTally and provides an interactive toggle (onToggleIgnoreList) that dynamically adjusts container dialog heights using transitionend event listeners.Important
Both getCauseChain and getAggregateErrors enforce a maximum recursion depth of 5 to prevent stack overflow vulnerabilities and infinite processing loops when handling circular or deeply nested error causes.
Sources: packages/next/src/next-devtools/dev-overlay/utils/get-error-by-type.ts:91-96, packages/next/src/next-devtools/dev-overlay/utils/get-error-by-type.ts:129-135