Open-Source Wikis

/

Next.js

/

How to contribute

/

Debugging

vercel/next.js

Debugging

The framework provides a handful of debug surfaces for digging into runtime behavior, build internals, and test failures.

Verbose logs

DEBUG=next:* pnpm next dev    # all next: namespaces
DEBUG=next:router pnpm next dev # one namespace

The debug package (github.com/debug-js/debug) is used throughout the codebase. Common namespaces:

  • next:* — everything
  • next:router — route matching and rewrites
  • next:fontnext/font resolution
  • next:trace — internal tracing

Full stack traces in dev

By default the dev server collapses internal frames into at ignore-listed frames to keep user-facing errors readable. Disable that filter with:

__NEXT_SHOW_IGNORE_LISTED=true pnpm next dev

Implementation: packages/next/src/server/patch-error-inspect.ts.

Inspecting with the Node debugger

pnpm debug      # node --inspect
pnpm debug-brk  # node --inspect-brk

These wrap packages/next/dist/bin/next with --inspect[-brk] plus --enable-source-maps and --trace-deprecation. Attach Chrome DevTools at chrome://inspect or your IDE's Node debugger.

Source maps

Two gotchas to know:

  1. findSourceMap() in Node only works when --enable-source-maps is passed (or returns undefined silently).
  2. Source map paths differ across compilers: webpack writes ./src/..., tsc writes src/.... Code that consumes them needs to try multiple formats.

Source map handling lives in packages/next/src/server/lib/source-maps.ts and packages/next/src/server/lib/get-source-map-from-file.ts.

Internal process.cwd() differences

process.cwd() produces different paths in tests vs production (test fixtures usually live under a temp directory). Stack-trace formatting that relies on cwd for relative paths needs to be tested in both contexts.

Bundling and module-resolution issues

When something resolves the "wrong" file or pulls in unexpected modules:

  1. Drop NEXT_SKIP_ISOLATE=1. Without isolation, tests use the local dist/ directly and hide module-resolution bugs that only show up when Next.js is packed as a real npm package.
  2. Inspect the route trace. .next/trace and the nft.json files emitted by packages/next/src/build/collect-build-traces.ts tell you which files each route ships.
  3. Webpack stats diff. For webpack-specific regressions, dump stats with next build --profile (or use @next/bundle-analyzer) and compare before/after.

The runtime-debug agent skill documents this workflow with concrete commands.

Edge runtime quirks

The edge runtime is a sandboxed VM (@edge-runtime/vm) that exposes only Web Standards. Common pitfalls:

  • No Node importsnode:stream, fs, path, etc. are not available. They must be guarded with if (process.env.NEXT_RUNTIME !== 'edge') blocks that webpack DCE can eliminate.
  • react-dom/server.edge differs from the .node build. Edge has no renderToPipeableStream; only renderToReadableStream. Snapshot tests can diverge between bundlers.
  • define-env.ts controls user bundle inlining, but the runtime bundle internals (the pre-compiled module.compiled.js) are independent. New flags consumed in those internals must also be wired through next-server.ts or export/worker.ts.

The dce-edge agent skill walks through DCE-safe require() patterns for edge.

Telemetry off

By default the framework collects anonymized telemetry. While debugging:

NEXT_TELEMETRY_DISABLED=1 pnpm next dev

Build trace inspection

Every next build emits an OpenTelemetry-formatted trace at .next/trace. Convert to a viewable format with the helper scripts:

node scripts/trace-to-tree.mjs .next/trace
node scripts/trace-to-event-format.mjs .next/trace > /tmp/build.json   # Chrome trace viewer format
node scripts/clean-trace-jaeger.mjs   # ship to Jaeger

The pnpm clean-trace-jaeger shortcut runs a clean build with TRACE_TARGET=JAEGER and forwards the trace to a local Jaeger.

Common dev-server crashes

  • Stale native binary — if Turbopack throws after a branch switch or pull, packages/next-swc/native/*.node may be stale. Delete it and run pnpm install to fetch the npm-published binary instead of an out-of-date locally-built one.
  • Cargo incremental ICE — if a Rust build crashes with an internal compiler error, delete */incremental/ directories under your cargo target dir (default target/, or wherever CARGO_TARGET_DIR points) and retry.
  • Frozen pnpm lockfile — if install fails after a major dep change, run pnpm install --no-frozen-lockfile (this is what pnpm version script does internally).

Reproducing test failures

The fastest path to reproducing a single failing CI test:

  1. Look at the failing job's env in pr-status output.
  2. Set IS_WEBPACK_TEST / IS_TURBOPACK_TEST / __NEXT_CACHE_COMPONENTS to match.
  3. Run the single test with pnpm test-<mode>-<bundler> path/to/test.ts.
  4. Capture output once: ... > /tmp/test-output.log 2>&1. Don't re-run.

If a snapshot disagrees, double-check the env flags before regenerating — env-sensitive snapshots will silently regenerate the wrong baseline if you pass different flags.

Patch-error-inspect

packages/next/src/server/patch-error-inspect.ts patches Node's error inspection to:

  • Filter internal frames (toggle with __NEXT_SHOW_IGNORE_LISTED)
  • Inject source-map-mapped frames
  • Format Error.cause chains

If error stacks look wrong, this file is usually the place to look.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Debugging – Next.js wiki | Factory