Next.js printed a stack frame that does not exist for an error whose
message ends with text that looks like a file location. A logged
connection failure read `at <unknown> (Error: connect ECONNREFUSED
::1:45999)` in front of its real frames.
`stacktrace-parser` tries five patterns on every line, and the pattern
for JavaScriptCore makes the `<name>@` prefix optional. That pattern
`:<line>:<column>`, and a line of an error message can end that way. A
JavaScriptCore frame always holds `@`, also at the top level, so the
prefix is not optional in a real stack.
The patch for `stacktrace-parser` now requires that prefix. A line of a
message no longer becomes a frame, and every JavaScriptCore frame still
parses, including one whose path holds a space.
A Turbopack build error puts the file and the position of the error in
its message, and the parser read that line as a frame as well. That
frame is gone now, and the location stays in the message. The snapshots
of the build errors record the change.
### Why?
Should come up with better solution that does not block PRs with git
conflict
x-ref:
https://vercel.slack.com/archives/C02CDC2ALJH/p1785263902728189?thread_ts=1785263687.502649&cid=C02CDC2ALJH
### How?
- Delete `errors.json`, the error-code SWC plugin, generated WASM, merge
driver, and validation/build tooling.
- Stop attaching error codes to server-rendering digests, redboxes, and
telemetry; native `Error.code` and `Error.name` remain available where
applicable.
- Remove the development-overlay error feedback UI, middleware, and
telemetry event that depended on stable codes.
- Update fixtures, snapshots, and guidance for code-free errors and
numeric-only digests.
<!-- NEXT_JS_LLM -->
An unhandled rejection was previously logged by up to three independent
process listeners at once: the render runtime's crash-prevention handler
in `process-error-handlers.ts` (a bare `console.error`), the router
server's `Log.error('unhandledRejection: ', err)`, and the dev server's
`logErrorWithOriginalStack`. The runtime handler must exist on every
deployment target (#77997), but on self-hosted `next start`/`next dev`
it shares a process with the router server's and dev server's listeners,
so a single rejection was logged multiple times in different formats.
THe first commits adds a test showing the current behavior where we log
multiple times.
The second commit introduces `registerUnhandledRejectionListener` and
`isUnhandledRejectionListenerRegistered` in `process-error-handlers.ts`,
and converts the router server and dev server to check-then-register
instead of installing their own rejection loggers:
- The listener function is shared via a `Symbol.for` key on
`globalThis`, so multiple copies of the module (e.g. in the pre-compiled
server bundle and in a route module bundle) register and detect a single
listener instance.
- The registration check queries
`process.listeners('unhandledRejection')` instead of a module-global
flag, so it stays accurate even after external code calls
`process.removeAllListeners`. `installProcessErrorHandlers` therefore
calls the register function unconditionally.
The `uncaughtException` handlers are left as they are; they have the
same duplication and could be consolidated the same way in a follow-up.
Next's dev error output (terminal logs and the browser overlay)
ignore-lists framework-internal stack frames. The forked
`EvalSourceMapDevToolPlugin` recomputes this ignore-list per module
because the vendored `webpack-sources` has no runtime `ignoreList`
support, so it drops the field when it combines a module's input source
map with the generated mappings. `shouldIgnorePath` matches on the
emitted source path, which works while a source resolves back to its
module. But a Next-internal module that ships an input source map (its
`.js.map`, which taskfile-swc marks entirely ignore-listed) resolves its
sources to the original files such as `src/server/web/adapter.ts`, which
no longer contain the `node_modules`/`next/dist` marker and no longer
resolve back to a module. Those frames then escape ignore-listing and
leak into both the terminal output and the overlay.
For such unresolved sources this falls back to the module's own resource
path, so a frame whose module lives in `node_modules`/`next/dist` stays
ignore-listed even when its source map points at the original source.
The fallback applies only to a `NormalModule`, whose sources all belong
to that one module; a `ConcatenatedModule` merges several modules'
sources under one map and is left to the path check, which the dev
`eval-source-map` devtool never produces anyway.
Runtime `"use cache"` code validated the default cache-life profile on
every invocation because `cacheLifeProfiles` was typed as optional with
partial profiles: `assertDefaultCacheLife` on the generate and RDC-read
paths, a per-`cacheLife()` presence `InvariantError`, and optional
chaining on reads.
Config normalization already guarantees this once:
`assignDefaultsAndValidate` builds the config from `{...defaultConfig,
...config}`, so `cacheLife` is always present, and it backfills the
`default` profile's `stale`, `revalidate`, and `expire`. This moves that
guarantee into the type. A new `ResolvedCacheLifeProfiles` (in
`config-shared`) types the `default` profile as `Required<CacheLife>`
and overrides `NextConfigComplete.cacheLife`, and the type is threaded,
non-optional, through the render options, work store, and the build,
export, and dev workers. Runtime code now reads
`cacheLifeProfiles.default` directly, and the asserts, the presence
guard, and the optional chaining are gone.
The proxy (middleware) work store is the one construction site without a
resolved profile: the proxy does not support `"use cache"`, so it never
reads `cacheLife`. It is given a sentinel whose `default` getter throws
if ever read, matching the "never read" sentinels already used for its
other unused render options.
### What?
Changes Turbopack's error overlay to show specific SWC diagnostic
messages as the error title instead of generic messages like "Parsing
ecmascript source code failed" or "Ecmascript file had an error".
### Why?
Previously, all SWC parse/analysis errors in Turbopack showed a generic
title (e.g. "Parsing ecmascript source code failed") in the redbox
header, with the actual specific error message buried in the description
below the code frame. This made it harder for developers to quickly
understand what went wrong.
**Before:**
```
Parsing ecmascript source code failed
> 1 | export default () => <div/
| ^
Expected '>', got '<eof>'
```
**After:**
```
Expected '>', got '<eof>'
> 1 | export default () => <div/
| ^
Parsing ecmascript source code failed
```
### How?
**Core change** in
`turbopack/crates/turbopack-swc-utils/src/emitter.rs`:
When the `IssueEmitter` has a `self.title` set (the generic title like
"Parsing ecmascript source code failed"), the SWC diagnostic message is
now used as the issue title, and the generic title is demoted to the
description. When `self.title` is not set, the existing behavior is
preserved (first line of message becomes title, rest becomes
description).
**Test updates** across ~15 test files:
Updated all `isTurbopack` branches in test expectations to reflect the
swapped title/description. Only Turbopack-specific branches were
modified; webpack and rspack expectations are unchanged.
**New test suite** (`test/development/app-dir/ecmascript-error-title/`):
Dedicated tests verifying that both syntax errors (e.g. `Expected '>',
got '<eof>'`) and analysis errors (e.g. `the name 'Table' is defined
multiple times`) show the specific SWC message as the redbox title.
**Turbopack snapshot updates:**
4 snapshot files renamed to reflect new titles (e.g. `Parsing ecmascript
source code failed-*.txt` → `Expression expected-*.txt`).
---------
Co-authored-by: Claude <noreply@anthropic.com>
update @next/rspack-core version to 1.0.2 and update the snapshot
other changes:
- packages/next/src/build/webpack-config.ts
Adjusted configuration to account for differences in default node config
between Rspack and Webpack.
- packages/next/src/shared/lib/format-webpack-messages.ts
Added a fallback to moduleIdentifier in cases where Rspack does not
correctly populate moduleName.
1. Fixed the incremental update bug in buildChunkGraph.
2. Fixed a bug in Rspack's built-in CssChunkingPlugin.
For detailed release information, please see
https://github.com/web-infra-dev/rspack/releases.
Note: All the faulty Rspack test cases on GitHub, from what I can see,
either time out or also produce errors in Rspack version 1.5.0.
---------
Co-authored-by: Benjamin Woodruff <benjamin.woodruff@vercel.com>
Enabling `experimental.isolatedDevBuild` required many changes to the
current workflow, so we will incrementally roll out to the tests.
Enabling on test-dev instead of test-experimental-dev because
`-experimental` CIs are filtered via `experimental-tests-manifest.json`
and they don't cover all tests. We want to enable this feature by
default so we should ensure this incremental rollout is covered on all
test cases.
The flag was enabled for `test-experimental-dev` at
https://github.com/vercel/next.js/pull/84099, and this PR moves the flag
to the `test-dev` job.
1. ~~test-experimental-dev
([link](https://github.com/vercel/next.js/pull/84099))~~
2. test-dev (here)
3. test-prod
4. test-integration
5. test-unit
6. Enable by default, remove the flag, and update the rest
x-ref: https://github.com/vercel/next.js/pull/84043
### What?
In development give the module factory a useful name, so it's clear in stack traces that this is the module evaluation part of the execution.
This also fixes some bugs with the stack trace parser, which seems to struggle if function names contain brackets. The automatically inferred function name would be the module id, which contains brackets.
Tests have been inconsistent due to flaky build-time failures caused by
AMP validation errors:
https://github.com/vercel/next.js/actions/runs/11807856104/attempts/1.
We’re updating the library version with the expectation that this will
resolve the issue.
```
info: undefined
Generating static pages (9/37)
Generating static pages (18/37)
Generating static pages (27/37)
Error occurred prerendering page "/amp-hybrid". Read more: https://nextjs.org/docs/messages/prerender-error
AssertionError: Assertion failed: WebAssembly is uninitialized
at new module$contents$goog$asserts_AssertionError (evalmachine.<anonymous>:102:1441)
at module$contents$goog$asserts_doAssertFailure (evalmachine.<anonymous>:103:354)
at goog.asserts.assertExists (evalmachine.<anonymous>:104:374)
at Object.module$contents$amp$validator_validateString [as validateString] (evalmachine.<anonymous>:2238:108)
at Validator.validateString (/tmp/next-install-89c7ccfd9a04886e2e88ccffb9ad709b236d4b8c8398fcdbb34c9c897118b9e9/node_modules/.pnpm/next@file+..+next-repo-99a8e0af0510a7a2958e71c9affe3d5d83d452a304c40ea8b352506d74651d57+packa_6sb2ai4rhstsynpbl53dxgpt7e/node_modules/next/dist/compiled/amphtml-validator/index.js:17:2057)
at validateAmp (/tmp/next-install-89c7ccfd9a04886e2e88ccffb9ad709b236d4b8c8398fcdbb34c9c897118b9e9/node_modules/.pnpm/next@file+..+next-repo-99a8e0af0510a7a2958e71c9affe3d5d83d452a304c40ea8b352506d74651d57+packa_6sb2ai4rhstsynpbl53dxgpt7e/node_modules/next/dist/export/routes/pages.js:100:34)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async exportPagesPage (/tmp/next-install-89c7ccfd9a04886e2e88ccffb9ad709b236d4b8c8398fcdbb34c9c897118b9e9/node_modules/.pnpm/next@file+..+next-repo-99a8e0af0510a7a2958e71c9affe3d5d83d452a304c40ea8b352506d74651d57+packa_6sb2ai4rhstsynpbl53dxgpt7e/node_modules/next/dist/export/routes/pages.js:134:17)
at async Span.traceAsyncFn (/tmp/next-install-89c7ccfd9a04886e2e88ccffb9ad709b236d4b8c8398fcdbb34c9c897118b9e9/node_modules/.pnpm/next@file+..+next-repo-99a8e0af0510a7a2958e71c9affe3d5d83d452a304c40ea8b352506d74651d57+packa_6sb2ai4rhstsynpbl53dxgpt7e/node_modules/next/dist/trace/trace.js:153:20)
at async exportPage (/tmp/next-install-89c7ccfd9a04886e2e88ccffb9ad709b236d4b8c8398fcdbb34c9c897118b9e9/node_modules/.pnpm/next@file+..+next-repo-99a8e0af0510a7a2958e71c9affe3d5d83d452a304c40ea8b352506d74651d57+packa_6sb2ai4rhstsynpbl53dxgpt7e/node_modules/next/dist/export/worker.js:336:18)
```
Note that this failure breaks the production integration test almost 10%
of times.

We will wait the server to respond with a compile success message after
a file is patched before proceeding to the next steps in the test to
reduce flakiness.
By doing so, we uncovered a few tests that were passing accidentally due
to flakiness of `patchFile`, and fixed them in the PR.
This enables DevTools (e.g. Chrome debugger) to collapse stackframes from 3rd party dependencies.
Webpack only. Turbopack added support in https://github.com/vercel/next.js/pull/71770. Replays from RSC will follow.
Had to fork `EvalSourceMapDevToolPlugin` (with blessing from @sokra) to be able to inject `ignoreList`.
For `source-map`, we can use https://github.com/mondaychen/devtools-ignore-webpack-plugin/ instead since we can operate on the assets on disk. I inlined it to iterate on it faster. Though it'd be faster for bundling to also fork `SourceMapDevToolPlugin` since `DevToolsIgnorePlugin` adds another parse/serialize roundtrip.
## test plan
We'll start leveraging `ignoreList` in the terminal as well which will allow us to write automated tests. I haven't found a way to automatically test this ignore-listing in browsers.
Note that this is on Chrome Beta. Chrome Stable does not ignore-list logged stacks yet. Only stacks of the actual `console` call or in the debugger.
(the frame from our console instrumentation is a bug that may be fixed once we populate our own sourcemaps)
`pnpm debug dev test/e2e/app-dir/server-source-maps/fixtures/default/`
`/ssr-error-log` shows
browser:


Node.js debugger doesn't seem to work. Will look at that in a follow-up
We already create server source maps in dev by default,
so we should make use of them.
To opt-out, run `next dev --disable-source-maps` instead.
Our internal `next-no-sourcemaps` script is now defunct.
Currently we only log warnings when we fail to parse config values and
then fall back to their defaults, this is very dangerous as this can
cause unexpected behavior and the warning log can be easy to miss. To
prevent this unexpected behavior this updates to treat these as errors
instead and fails the build if any invalid config exports are provided.
x-ref: NDX-190
## What
This PR introduces a new API `onRequestError` in `instrumentation.js`
convention, which can help you track the errors thrown from pages and
routes on server side.
### API
```ts
type RequestInfo = {
url: string
method: string
headers: Record<string, string | string [] | undefined>
}
type ErrorContext = {
routerKind: 'Pages Router' | 'App Router'
routePath: string
routeType: 'render' | 'route' | 'middleware'
}
export function onRequestError(error: unknown, request: RequestInfo, errorContext: ErrorContext) {
}
```
This experimental feature is now scoped behind an experimental env var
`__NEXT_EXPERIMENTAL_INSTRUMENTATION` now. You need to enable to use it
before the feature is fully ready off from experimental.
## Why
The purpose is to provide a way to track the server errors from Next.js
much easier, especially when users're uing an o11y provider such as
sentry/datadog/newrelic etc. to monitor server side exceptions. There're
different runtime (Node.js or Edge) and different type of routes (App
Router pages/API routes, Pages Router pages/API routes, middleware) that
makes the error tracking story more complex. This API will be an
universal way to get all the errors.
The reason of providing the related arguments like request info and
error context is aimed to provide more insights about associated
request, also the context about Next.js framework itself, like which
feature is throwing the error.
...with `assertHasRedbox` and `assertNoRedbox`.
`hasRedbox()` has a hardcoded timeout of 5s that is only required for
the negative assertion.
Instead, we now have dedicated assertions for the positive
(`assertHasRedbox`) and negative case (`assertNoRedbox`).
The negative assertion still has the hardcoded timeout.
But the positive assertion just retries until we find the Redbox.
This speeds up tests using the positive assertion.
Removing `hasRedbox` also uncovered some unused expressions e.g. `await
hasRedbox(browser)`.
These expressions probably wanted to use `expect(await
hasRedbox(browser)).toBe(true)
### Description
This PR refactors existing `analysis/get-static-page-info`, moves over
most of parse / ast visiting logic into next-swc's rust codebase. By
having this, turbopack can reuse same logic to extract info for the
analysis. Also as a side effect, this removes JS side parse which is
known to be inefficient due to serialization / deserialization.
The entrypoint `getPageStaticInfo` is still in the existing
`get-page-static-info`, only for extracting / visiting logic is moved.
There are some JS specific context to postprocess extracted information
which would require additional effort to move into.
Closes PACK-2088