Skip to content

Add multi-project daemon support for next dev/build#92022

Draft
sokra wants to merge 7 commits intocanaryfrom
sokra/multi-project
Draft

Add multi-project daemon support for next dev/build#92022
sokra wants to merge 7 commits intocanaryfrom
sokra/multi-project

Conversation

@sokra
Copy link
Copy Markdown
Member

@sokra sokra commented Mar 28, 2026

What?

Adds scaffolding for running multiple Next.js projects simultaneously with a shared Turbopack daemon process. When two or more --project flags are passed to next dev or next build, the CLI:

  1. Spawns a Turbopack daemon process (next internal turbopack-daemon <socket>)
  2. Spawns N Next.js worker processes (one per project), each connecting to the daemon via --turbopack-daemon <socket>
  3. The daemon and workers communicate over Unix domain sockets (Linux/macOS) or Windows named pipes

CLI syntax

# Multi-project dev with per-project ports
next dev --project ./app1 --port 3000 --project ./app2 --port 3001

# Multi-project build
next build --project ./app1 --project ./app2

# Per-project bundler selection
next dev --project ./app1 --turbopack --project ./app2 --webpack

Single-project usage (next dev / next build without --project) is completely unchanged.

Why?

Multi-project (monorepo) setups currently require running separate next dev / next build processes, each with its own Turbopack instance. Sharing a single Turbopack daemon across projects enables:

  • Shared persistent cache and file watching
  • Reduced memory footprint for monorepos
  • Foundation for cross-project optimizations

How?

TypeScript layer

File Purpose
packages/next/src/lib/multi-project.ts parseProjectGroups() argv parser, socket path generation, daemon/worker orchestration
packages/next/src/cli/internal/turbopack-daemon.ts Hidden next internal turbopack-daemon subcommand
packages/next/src/bin/next.ts --turbopack-daemon hidden option on dev/build, multi-project detection, daemon subcommand registration
packages/next/src/cli/next-dev.ts turbopackDaemon option, NEXT_TURBOPACK_DAEMON_SOCKET env propagation to forked server
packages/next/src/cli/next-build.ts Same env propagation for build mode
packages/next/src/build/swc/types.ts startTurbopackDaemon, connectTurbopackDaemon, daemon param on createProject
packages/next/src/build/swc/index.ts Wires daemon methods in loadNative, threads daemon through createProjectprojectNew

Rust IPC layer (in crates/next-api/src/ipc/)

File Purpose
protocol.rs Bincode DaemonRequest / DaemonResponse / DaemonResult enums. Reuses ProjectOptions, PartialProjectOptions, etc. directly from next-api (no Wire* duplication). Adds TurboEngineOptions and StackFrame for types that don't yet have pure-Rust equivalents.
client.rs DaemonClient — connects to socket, length-prefixed framing, async call/subscribe with oneshot/mpsc channels
server.rs Daemon server loop (Unix UnixListener / Windows named pipes), "READY" stdout signaling, per-connection handler, stub request dispatcher
daemon.rs Public start_daemon() / connect_daemon() API

NAPI layer (in crates/next-napi-bindings/)

  • start_turbopack_daemon(socket_path) — starts the daemon server (blocks forever)
  • connect_turbopack_daemon(socket_path) — returns opaque DaemonHandle External
  • project_new gains optional daemon: External<DaemonHandle> parameter — when set, short-circuits to IPC instead of full in-process TurboTasks setup
  • ProjectInstance refactored with Option fields + RemoteProject struct to support both local and remote (daemon-backed) projects
  • All downstream field accesses (turbopack_ctx, container) migrated to ctx() / container() accessor methods

Current state

The daemon server returns stub responses for most operations — full ProjectContainer dispatch will be wired up in follow-up PRs. The IPC protocol, framing, client/server connection, and CLI orchestration are complete and functional.

Test plan

  • parseProjectGroups unit tests (6 tests) — pnpm jest test/e2e/multi-project/multi-project.test.ts
  • Rust IPC protocol roundtrip test — cargo test -p next-api --lib ipc::protocol::tests
  • cargo check -p next-api -p next-napi-bindings compiles cleanly
  • E2E multi-project dev/build tests (requires full daemon dispatch — follow-up)

sokra and others added 2 commits March 27, 2026 23:36
When multiple --project flags are detected, spawn a shared Turbopack daemon
process and N worker Next.js processes that communicate via Unix domain sockets
(or Windows named pipes). This commit adds:

- CLI: --project flag parsing, --turbopack-daemon hidden flag, `next internal
  turbopack-daemon` subcommand, multi-project orchestrator
- Rust IPC: bincode protocol types, daemon server, client stub in next-api
- NAPI: startTurbopackDaemon and connectTurbopackDaemon entry points
- JS bindings: daemon handle threading through createProject
- Test fixtures and parseProjectGroups unit tests

The daemon server currently returns stub responses for most operations. The
actual ProjectContainer dispatch will be wired up in a follow-up.

Co-Authored-By: Claude <noreply@anthropic.com>
…tInstance

- Add optional `daemon` parameter to `project_new` for IPC path
- Refactor `ProjectInstance` to support both local and remote (daemon-backed)
  projects via `Option` fields and `RemoteProject` struct
- Add `ctx()` and `container()` accessor methods on `ProjectInstance`
- When daemon is provided, short-circuit to IPC call instead of full in-process
  setup (tracing, profiling, TurboTasks creation, etc.)

Co-Authored-By: Claude <noreply@anthropic.com>
@nextjs-bot nextjs-bot added created-by: Turbopack team PRs by the Turbopack team. tests Turbopack Related to Turbopack with Next.js. type: next labels Mar 28, 2026
The WASM fallback binding object was missing startTurbopackDaemon and
connectTurbopackDaemon, and the generated-native.d.ts declaration for
projectNew was missing the new optional daemon parameter. Both caused
type errors during pnpm build / tsc.

Co-Authored-By: Claude <noreply@anthropic.com>
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Mar 28, 2026

Merging this PR will not alter performance

✅ 17 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing sokra/multi-project (2b37d21) with canary (7bce97d)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

sokra and others added 2 commits March 28, 2026 03:42
The WASM binding stub added for startTurbopackDaemon/connectTurbopackDaemon
introduced a new error message string that must be registered in errors.json.
Running pnpm build detected it automatically via the check_error_codes step.

Co-Authored-By: Claude <noreply@anthropic.com>
The initial `inner` allocation at the top of `connect` was unused —
the real client is built a few lines later after the socket is opened.
Pointed out in code review.

Co-Authored-By: Claude <noreply@anthropic.com>
@nextjs-bot
Copy link
Copy Markdown
Collaborator

nextjs-bot commented Mar 28, 2026

Failing test suites

Commit: 2b37d21 | About building and testing Next.js

pnpm test-start-turbo test/production/dynamic-css-client-navigation/react-lazy.test.ts (turbopack) (job)

  • dynamic-css-client-navigation react lazy nodejs > should not remove style when navigating from static imported component to react lazy at runtime nodejs (DD)
Expand output

● dynamic-css-client-navigation react lazy nodejs › should not remove style when navigating from static imported component to react lazy at runtime nodejs

expect(received).toBe(expected) // Object.is equality

Expected: "rgb(255, 0, 0)"
Received: null

  22 |       )
  23 |
> 24 |       expect(buttonBgColor).toBe('rgb(255, 0, 0)')
     |                             ^
  25 |     })
  26 |   }
  27 | )

  at Object.toBe (production/dynamic-css-client-navigation/react-lazy.test.ts:24:29)

pnpm test test/integration/i18n-support-base-path/test/index.test.ts (turbopack) (job)

  • i18n Support basePath > development mode > should navigate with locale prop correctly GSP (DD)
  • i18n Support basePath > development mode > should navigate with locale false correctly (DD)
Expand output

● i18n Support basePath › development mode › should navigate with locale prop correctly GSP

expect(received).toEqual(expected) // deep equality

- Expected  - 1
+ Received  + 8

- Array []
+ Array [
+   "[HMR] Invalid message: {\"type\":\"isrManifest\",\"data\":{\"/links?nextLocale=nl\":false,\"/another\":false,\"/links?nextLocale=fr\":false,\"/rewrite-4\":false,\"/rewrite-3\":false,\"/rewrite-2\":false,\"/rewrite-1\":false,\"/404\":true,\"/[post]\":true,\"/\":true,\"/dynamic/[slug]\":true,\"/gsp/no-fallback/first\":true,\"/gsp/fallback/first\":true,\"/links\":false,\"/gsp/fallback/mixed-not-found-redirect\":false,\"/locale-false?nextLocale=fr\":false,\"/gssp?page=1\":false,\"/links?nextLocale=go-BE\":false,\"/links?nextLocale=go\":false,\"/developments\":false}}
+ TypeError: Cannot read properties of undefined (reading 'components')
+     at handleStaticIndicator (http://localhost:38605/docs/_next/static/chunks/packages_next_dist_client_0o_x56p._.js:2912:46)
+     at processMessage (http://localhost:38605/docs/_next/static/chunks/packages_next_dist_client_0o_x56p._.js:2926:17)
+     at http://localhost:38605/docs/_next/static/chunks/packages_next_dist_client_0o_x56p._.js:2796:13
+     at WebSocket.handleMessage (http://localhost:38605/docs/_next/static/chunks/packages_next_dist_client_0o_x56p._.js:2426:17)",
+ ]

  2357 |     expect(Object.fromEntries(parsedUrl.searchParams.entries())).toEqual({})
  2358 |     expect(await browser.eval('window.beforeNav')).toBe(1)
> 2359 |     expect(await browser.eval('window.caughtWarns')).toEqual([])
       |                                                      ^
  2360 |   })
  2361 |
  2362 |   it('should navigate with locale false correctly', async () => {

  at Object.toEqual (integration/i18n-support/test/shared.ts:2359:54)

● i18n Support basePath › development mode › should navigate with locale false correctly

expect(received).toEqual(expected) // deep equality

- Expected  - 1
+ Received  + 8

- Array []
+ Array [
+   "[HMR] Invalid message: {\"type\":\"isrManifest\",\"data\":{\"/locale-false?nextLocale=fr\":false,\"/gsp/fallback/first\":true,\"/links?nextLocale=nl\":false,\"/another\":false,\"/links?nextLocale=fr\":false,\"/rewrite-4\":false,\"/rewrite-3\":false,\"/rewrite-2\":false,\"/rewrite-1\":false,\"/404\":true,\"/[post]\":true,\"/\":true,\"/dynamic/[slug]\":true,\"/gsp/no-fallback/first\":true,\"/links\":false,\"/gsp/fallback/mixed-not-found-redirect\":false,\"/gssp?page=1\":false,\"/links?nextLocale=go-BE\":false,\"/links?nextLocale=go\":false,\"/developments\":false}}
+ TypeError: Cannot read properties of undefined (reading 'components')
+     at handleStaticIndicator (http://localhost:38605/docs/_next/static/chunks/packages_next_dist_client_0o_x56p._.js:2912:46)
+     at processMessage (http://localhost:38605/docs/_next/static/chunks/packages_next_dist_client_0o_x56p._.js:2926:17)
+     at http://localhost:38605/docs/_next/static/chunks/packages_next_dist_client_0o_x56p._.js:2796:13
+     at WebSocket.handleMessage (http://localhost:38605/docs/_next/static/chunks/packages_next_dist_client_0o_x56p._.js:2426:17)",
+ ]

  2483 |     expect(Object.fromEntries(parsedUrl.searchParams.entries())).toEqual({})
  2484 |     expect(await browser.eval('window.beforeNav')).toBe(1)
> 2485 |     expect(await browser.eval('window.caughtWarns')).toEqual([])
       |                                                      ^
  2486 |   })
  2487 |
  2488 |   it('should navigate with locale false correctly GSP', async () => {

  at Object.toEqual (integration/i18n-support/test/shared.ts:2485:54)

pnpm test-start test/e2e/app-dir-export/test/start.test.ts (job)

  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should support parallel route tab bars (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should match parallel routes (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should match parallel routes in route groups (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should throw a 404 when no matching parallel route is found (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should render nested parallel routes (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should support layout files in parallel routes (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should only scroll to the parallel route that was navigated to (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should apply the catch-all route to the parallel route if no matching route is found (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should match the catch-all routes of the more specific path, if there is more than one catch-all route (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should navigate with a link with prefetch=false (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should display all parallel route params with useParams (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should load CSS for a default page that exports another page (DD)
  • parallel-routes-and-interception (trailingSlash: false) > parallel routes > should handle a loading state (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting > should render intercepted route (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting > should render an intercepted route from a slot (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting > should render an intercepted route at the top level from a nested path (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting > should render intercepted route from a nested route (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting > should re-render the layout on the server when it had a default child route (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting > should render modal when paired with parallel routes (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting > should support intercepting with beforeFiles rewrites (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting > should support intercepting local dynamic sibling routes (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting > should intercept on routes that contain hyphenated/special dynamic params (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting > should not have /default paths in the prerender manifest (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting with dynamic catch-all routes > should render intercepted route (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting with dynamic optional catch-all routes > should render intercepted route (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting with dynamic routes > should render intercepted route (DD)
  • parallel-routes-and-interception (trailingSlash: false) > route intercepting with prerendered dynamic routes > should render intercepted route (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should support parallel route tab bars (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should match parallel routes (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should match parallel routes in route groups (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should throw a 404 when no matching parallel route is found (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should render nested parallel routes (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should support layout files in parallel routes (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should only scroll to the parallel route that was navigated to (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should apply the catch-all route to the parallel route if no matching route is found (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should match the catch-all routes of the more specific path, if there is more than one catch-all route (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should navigate with a link with prefetch=false (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should display all parallel route params with useParams (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should load CSS for a default page that exports another page (DD)
  • parallel-routes-and-interception (trailingSlash: true) > parallel routes > should handle a loading state (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting > should render intercepted route (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting > should render an intercepted route from a slot (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting > should render an intercepted route at the top level from a nested path (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting > should render intercepted route from a nested route (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting > should re-render the layout on the server when it had a default child route (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting > should render modal when paired with parallel routes (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting > should support intercepting with beforeFiles rewrites (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting > should support intercepting local dynamic sibling routes (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting > should intercept on routes that contain hyphenated/special dynamic params (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting > should not have /default paths in the prerender manifest (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting with dynamic catch-all routes > should render intercepted route (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting with dynamic optional catch-all routes > should render intercepted route (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting with dynamic routes > should render intercepted route (DD)
  • parallel-routes-and-interception (trailingSlash: true) > route intercepting with prerendered dynamic routes > should render intercepted route (DD)
  • parallel-routes-and-interception-conflicting-pages > should gracefully handle when two page segments match the children parallel slot (DD)
Expand output

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should support parallel route tab bars

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should match parallel routes

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should match parallel routes in route groups

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should throw a 404 when no matching parallel route is found

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should render nested parallel routes

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should support layout files in parallel routes

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should only scroll to the parallel route that was navigated to

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should apply the catch-all route to the parallel route if no matching route is found

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should match the catch-all routes of the more specific path, if there is more than one catch-all route

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should navigate with a link with prefetch=false

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should display all parallel route params with useParams

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should load CSS for a default page that exports another page

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › parallel routes › should handle a loading state

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting with dynamic routes › should render intercepted route

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting with prerendered dynamic routes › should render intercepted route

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting with dynamic optional catch-all routes › should render intercepted route

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting with dynamic catch-all routes › should render intercepted route

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting › should render intercepted route

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting › should render an intercepted route from a slot

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting › should render an intercepted route at the top level from a nested path

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting › should render intercepted route from a nested route

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting › should re-render the layout on the server when it had a default child route

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting › should render modal when paired with parallel routes

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting › should support intercepting with beforeFiles rewrites

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting › should support intercepting local dynamic sibling routes

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting › should intercept on routes that contain hyphenated/special dynamic params

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: true) › route intercepting › should not have /default paths in the prerender manifest

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:26:59
      at Array.forEach (<anonymous>)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:23:28)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should support parallel route tab bars

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should match parallel routes

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should match parallel routes in route groups

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should throw a 404 when no matching parallel route is found

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should render nested parallel routes

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should support layout files in parallel routes

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should only scroll to the parallel route that was navigated to

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should apply the catch-all route to the parallel route if no matching route is found

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should match the catch-all routes of the more specific path, if there is more than one catch-all route

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should navigate with a link with prefetch=false

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should display all parallel route params with useParams

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should load CSS for a default page that exports another page

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › parallel routes › should handle a loading state

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting with dynamic routes › should render intercepted route

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting with prerendered dynamic routes › should render intercepted route

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting with dynamic optional catch-all routes › should render intercepted route

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting with dynamic catch-all routes › should render intercepted route

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting › should render intercepted route

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting › should render an intercepted route from a slot

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting › should render an intercepted route at the top level from a nested path

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting › should render intercepted route from a nested route

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting › should re-render the layout on the server when it had a default child route

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting › should render modal when paired with parallel routes

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting › should support intercepting with beforeFiles rewrites

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting › should support intercepting local dynamic sibling routes

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting › should intercept on routes that contain hyphenated/special dynamic params

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception (trailingSlash: false) › route intercepting › should not have /default paths in the prerender manifest

createNext called without destroying previous instance

  235 |   try {
  236 |     if (nextInstance) {
> 237 |       throw new Error(`createNext called without destroying previous instance`)
      |             ^
  238 |     }
  239 |
  240 |     setupTracing()

  at createNext (lib/e2e-utils/index.ts:237:13)
  at Object.createNext (lib/e2e-utils/index.ts:331:20)

● parallel-routes-and-interception-conflicting-pages › should gracefully handle when two page segments match the children parallel slot

thrown: "Exceeded timeout of 120000 ms for a hook.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

  328 |   let next: NextInstance | undefined
  329 |   if (!skipped) {
> 330 |     beforeAll(async () => {
      |     ^
  331 |       next = await createNext(options)
  332 |     })
  333 |     afterAll(async () => {

  at beforeAll (lib/e2e-utils/index.ts:330:5)
  at e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:1060:42
  at Object.describe (e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts:1059:1)

● Test suite failed to run

next instance not destroyed before exiting, make sure to call .destroy() after the tests after finished

  209 |     if (nextInstance) {
  210 |       await nextInstance.destroy()
> 211 |       throw new Error(
      |             ^
  212 |         `next instance not destroyed before exiting, make sure to call .destroy() after the tests after finished`
  213 |       )
  214 |     }

  at Object.<anonymous> (lib/e2e-utils/index.ts:211:13)

- Remove 4 unused imports in ipc/protocol.rs (DebugBuildPaths, DefineEnv,
  DraftModeOptions, WatchOptions) flagged by -D unused-imports
- Remove unused HashMap import in ipc/server.rs
- Rewrite loop+match as while-let in ipc/client.rs per clippy::while-let-loop
- Reformat multi-project.ts with prettier (trailing whitespace)
- Fix multi-project unit test: remove explicit @jest/globals import (globals
  are available via root tsconfig), fix module path to relative reference

Co-Authored-By: Claude <noreply@anthropic.com>
@nextjs-bot
Copy link
Copy Markdown
Collaborator

nextjs-bot commented Mar 28, 2026

Stats from current PR

🔴 1 regression

Metric Canary PR Change Trend
node_modules Size 485 MB 485 MB 🔴 +73.7 kB (+0%) █████
📊 All Metrics
📖 Metrics Glossary

Dev Server Metrics:

  • Listen = TCP port starts accepting connections
  • First Request = HTTP server returns successful response
  • Cold = Fresh build (no cache)
  • Warm = With cached build artifacts

Build Metrics:

  • Fresh = Clean build (no .next directory)
  • Cached = With existing .next directory

Change Thresholds:

  • Time: Changes < 50ms AND < 10%, OR < 2% are insignificant
  • Size: Changes < 1KB AND < 1% are insignificant
  • All other changes are flagged to catch regressions

⚡ Dev Server

Metric Canary PR Change Trend
Cold (Listen) 455ms 455ms █▁▁▁▁
Cold (Ready in log) 436ms 436ms █▁▁▁▁
Cold (First Request) 1.109s 1.096s █▂▂▂▂
Warm (Listen) 456ms 456ms █▁▁▁▁
Warm (Ready in log) 442ms 440ms █▁▁▁▁
Warm (First Request) 343ms 340ms █▁▁▁▁
📦 Dev Server (Webpack) (Legacy)

📦 Dev Server (Webpack)

Metric Canary PR Change Trend
Cold (Listen) 456ms 456ms █▁▁▁▁
Cold (Ready in log) 439ms 438ms █▁▁▁▁
Cold (First Request) 1.857s 1.874s █▁▃▃▁
Warm (Listen) 455ms 456ms █▁▁▁▁
Warm (Ready in log) 438ms 439ms █▁▁▁▁
Warm (First Request) 1.885s 1.883s █▁▃▃▁

⚡ Production Builds

Metric Canary PR Change Trend
Fresh Build 3.796s 3.746s █▁▁▁▁
Cached Build 3.831s 3.829s █▁▁▁▁
📦 Production Builds (Webpack) (Legacy)

📦 Production Builds (Webpack)

Metric Canary PR Change Trend
Fresh Build 14.412s 14.441s █▁▁▂▁
Cached Build 14.506s 14.567s █▁▁▁▁
node_modules Size 485 MB 485 MB 🔴 +73.7 kB (+0%) █████
📦 Bundle Sizes

Bundle Sizes

⚡ Turbopack

Client

Main Bundles
Canary PR Change
02fkg8wfh0iju.js gzip 9.19 kB N/A -
050zwt5xh_0tx.js gzip 10.4 kB N/A -
06rvbj82bhyo0.js gzip 13 kB N/A -
087fzjd-gvlzv.js gzip 450 B N/A -
0cz1d0mv5g_q7.js gzip 39.4 kB 39.4 kB
0n_dy402y1-7_.js gzip 156 B N/A -
0ppxcl_z43mad.js gzip 8.52 kB N/A -
0rfpjmgf56q96.js gzip 153 B N/A -
10ra7sic7j_q9.js gzip 65.7 kB N/A -
18io-8oa2n1ne.js gzip 170 B N/A -
19oha6-znmkcv.js gzip 8.55 kB N/A -
1elt1qium-r2m.css gzip 115 B 115 B
1l7x4o3ggu40i.js gzip 156 B N/A -
1r0glxjr_p-lz.js gzip 70.8 kB N/A -
1tfbce4nozgvk.js gzip 157 B N/A -
1yl5jy653a49k.js gzip 13.7 kB N/A -
2524qmz0et54b.js gzip 7.61 kB N/A -
26elcgxnn9zjd.js gzip 8.52 kB N/A -
2900hudr6gvm0.js gzip 2.28 kB N/A -
293sfm6gr995x.js gzip 158 B N/A -
2aytuzfsxs-ng.js gzip 162 B N/A -
2dtal7ljiqtvy.js gzip 158 B N/A -
2ihlsvbo2c9e8.js gzip 215 B 215 B
2lv2js3kmdeho.js gzip 8.48 kB N/A -
2pe03oj3fi47x.js gzip 158 B N/A -
2rehygrd36hqv.js gzip 8.58 kB N/A -
2srwswih0m9_h.js gzip 13.3 kB N/A -
3-p9p9mheqhzx.js gzip 8.55 kB N/A -
31030bryqpolg.js gzip 8.53 kB N/A -
313uw4pi84-nn.js gzip 155 B N/A -
31dx5nmrzzuy7.js gzip 225 B N/A -
3ha7h58bte-tq.js gzip 49 kB N/A -
3iu80eefg23ae.js gzip 9.77 kB N/A -
3k-48b78ys_vy.js gzip 10.1 kB N/A -
3m7-5rfj0avoz.js gzip 12.9 kB N/A -
3oldhmkmh_ttt.js gzip 156 B N/A -
3son74bv6_ukz.js gzip 157 B N/A -
3uqce_6sa526g.js gzip 8.47 kB N/A -
3yurjqk-sjs3y.js gzip 1.46 kB N/A -
421vzwdt9j1b_.js gzip 5.62 kB N/A -
44g0z4do5ybko.js gzip 160 B N/A -
turbopack-0b..p5tq.js gzip 4.16 kB N/A -
turbopack-0i..btad.js gzip 4.14 kB N/A -
turbopack-0r..wket.js gzip 4.17 kB N/A -
turbopack-0y..64ab.js gzip 4.16 kB N/A -
turbopack-1-..0e4u.js gzip 4.16 kB N/A -
turbopack-11..u-7j.js gzip 4.16 kB N/A -
turbopack-1j..jhqp.js gzip 4.16 kB N/A -
turbopack-1n..ih5x.js gzip 4.16 kB N/A -
turbopack-1u..5j9t.js gzip 4.16 kB N/A -
turbopack-1v..moi5.js gzip 4.16 kB N/A -
turbopack-22..gp0k.js gzip 4.16 kB N/A -
turbopack-2y..n7l-.js gzip 4.16 kB N/A -
turbopack-30..wnxd.js gzip 4.16 kB N/A -
turbopack-39..tjse.js gzip 4.16 kB N/A -
03dgzoo-qf3sm.js gzip N/A 9.19 kB -
05tx5f25dlivn.js gzip N/A 8.53 kB -
0c7ez6p2qc57f.js gzip N/A 5.62 kB -
0hh8avilv0ojg.js gzip N/A 157 B -
0k64vlvxmxe37.js gzip N/A 157 B -
0n95_eeqgrhcd.js gzip N/A 13.7 kB -
0o8_7qesyk05v.js gzip N/A 156 B -
0qnwuk92m8i7o.js gzip N/A 10.4 kB -
0r4wrn6n0ue2m.js gzip N/A 8.55 kB -
0rp0fodtbt_6m.js gzip N/A 8.52 kB -
0sfck-km4dl1k.js gzip N/A 8.47 kB -
0x0xuhmxzwkp8.js gzip N/A 8.47 kB -
1-wdvgxnzicj7.js gzip N/A 1.46 kB -
1083kmmn904k-.js gzip N/A 156 B -
11u6nxujb2eg4.js gzip N/A 450 B -
19jz3mojsh446.js gzip N/A 154 B -
1fgcxfy5evsmo.js gzip N/A 65.7 kB -
1h2m6kg4-m7d3.js gzip N/A 7.6 kB -
1hyxrs-fqu4mr.js gzip N/A 160 B -
1r_rhe44k4b7o.js gzip N/A 169 B -
1yshlunbh203u.js gzip N/A 156 B -
29__un8dvi9q7.js gzip N/A 162 B -
2f0isyv74vou4.js gzip N/A 155 B -
2k9ax08cjl2id.js gzip N/A 12.9 kB -
2lms6k76q5-6m.js gzip N/A 13.3 kB -
2p33dcb2dofml.js gzip N/A 158 B -
2q3hz-jtbjs52.js gzip N/A 9.77 kB -
2qx4twi9i3xus.js gzip N/A 2.28 kB -
2srnqic6tvxxd.js gzip N/A 8.52 kB -
2z_xgkr8n426y.js gzip N/A 70.8 kB -
30l7m4nayp73a.js gzip N/A 8.55 kB -
35usk0rt_jbub.js gzip N/A 159 B -
38rr7d3kfutni.js gzip N/A 13 kB -
3axctu0hicx1a.js gzip N/A 49 kB -
3h_ecpiaatwgc.js gzip N/A 10.1 kB -
3ity0aahajapd.js gzip N/A 225 B -
42ip5rlu748dz.js gzip N/A 156 B -
43mlw9dy_8f02.js gzip N/A 8.58 kB -
turbopack-0-..xx31.js gzip N/A 4.14 kB -
turbopack-02..u0m7.js gzip N/A 4.16 kB -
turbopack-05..90-i.js gzip N/A 4.16 kB -
turbopack-13..kqkq.js gzip N/A 4.16 kB -
turbopack-1g..-8ng.js gzip N/A 4.16 kB -
turbopack-1p..x5mn.js gzip N/A 4.16 kB -
turbopack-22..2w9-.js gzip N/A 4.16 kB -
turbopack-22..oq78.js gzip N/A 4.16 kB -
turbopack-28..y___.js gzip N/A 4.16 kB -
turbopack-2p..jy4_.js gzip N/A 4.17 kB -
turbopack-2r..u-us.js gzip N/A 4.16 kB -
turbopack-36..lzmc.js gzip N/A 4.16 kB -
turbopack-3a..9uds.js gzip N/A 4.16 kB -
turbopack-3v..ajfh.js gzip N/A 4.16 kB -
Total 464 kB 464 kB ✅ -8 B

Server

Middleware
Canary PR Change
middleware-b..fest.js gzip 720 B 714 B
Total 720 B 714 B ✅ -6 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 431 B 434 B
Total 431 B 434 B ⚠️ +3 B

📦 Webpack

Client

Main Bundles
Canary PR Change
5528-HASH.js gzip 5.54 kB N/A -
6280-HASH.js gzip 60.7 kB N/A -
6335.HASH.js gzip 169 B N/A -
912-HASH.js gzip 4.59 kB N/A -
e8aec2e4-HASH.js gzip 62.8 kB N/A -
framework-HASH.js gzip 59.7 kB 59.7 kB
main-app-HASH.js gzip 255 B 255 B
main-HASH.js gzip 39.3 kB 39.2 kB
webpack-HASH.js gzip 1.68 kB 1.68 kB
262-HASH.js gzip N/A 4.59 kB -
2889.HASH.js gzip N/A 169 B -
5602-HASH.js gzip N/A 5.55 kB -
6948ada0-HASH.js gzip N/A 62.8 kB -
9544-HASH.js gzip N/A 61.4 kB -
Total 235 kB 235 kB ⚠️ +666 B
Polyfills
Canary PR Change
polyfills-HASH.js gzip 39.4 kB 39.4 kB
Total 39.4 kB 39.4 kB
Pages
Canary PR Change
_app-HASH.js gzip 194 B 194 B
_error-HASH.js gzip 183 B 180 B 🟢 3 B (-2%)
css-HASH.js gzip 331 B 330 B
dynamic-HASH.js gzip 1.81 kB 1.81 kB
edge-ssr-HASH.js gzip 256 B 256 B
head-HASH.js gzip 351 B 352 B
hooks-HASH.js gzip 384 B 383 B
image-HASH.js gzip 580 B 581 B
index-HASH.js gzip 260 B 260 B
link-HASH.js gzip 2.51 kB 2.51 kB
routerDirect..HASH.js gzip 320 B 319 B
script-HASH.js gzip 386 B 386 B
withRouter-HASH.js gzip 315 B 315 B
1afbb74e6ecf..834.css gzip 106 B 106 B
Total 7.98 kB 7.98 kB ✅ -1 B

Server

Edge SSR
Canary PR Change
edge-ssr.js gzip 125 kB 125 kB
page.js gzip 270 kB 270 kB
Total 395 kB 396 kB ⚠️ +220 B
Middleware
Canary PR Change
middleware-b..fest.js gzip 620 B 614 B
middleware-r..fest.js gzip 156 B 155 B
middleware.js gzip 44 kB 43.9 kB
edge-runtime..pack.js gzip 842 B 842 B
Total 45.6 kB 45.5 kB ✅ -118 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 715 B 718 B
Total 715 B 718 B ⚠️ +3 B
Build Cache
Canary PR Change
0.pack gzip 4.34 MB 4.34 MB
index.pack gzip 110 kB 110 kB
index.pack.old gzip 109 kB 110 kB 🔴 +1.32 kB (+1%)
Total 4.56 MB 4.56 MB ✅ -3.18 kB

🔄 Shared (bundler-independent)

Runtimes
Canary PR Change
app-page-exp...dev.js gzip 335 kB 335 kB
app-page-exp..prod.js gzip 185 kB 185 kB
app-page-tur...dev.js gzip 335 kB 335 kB
app-page-tur..prod.js gzip 185 kB 185 kB
app-page-tur...dev.js gzip 331 kB 331 kB
app-page-tur..prod.js gzip 183 kB 183 kB
app-page.run...dev.js gzip 332 kB 332 kB
app-page.run..prod.js gzip 184 kB 184 kB
app-route-ex...dev.js gzip 76.2 kB 76.2 kB
app-route-ex..prod.js gzip 51.9 kB 51.9 kB
app-route-tu...dev.js gzip 76.3 kB 76.3 kB
app-route-tu..prod.js gzip 51.9 kB 51.9 kB
app-route-tu...dev.js gzip 75.9 kB 75.9 kB
app-route-tu..prod.js gzip 51.6 kB 51.6 kB
app-route.ru...dev.js gzip 75.8 kB 75.8 kB
app-route.ru..prod.js gzip 51.6 kB 51.6 kB
dist_client_...dev.js gzip 324 B 324 B
dist_client_...dev.js gzip 326 B 326 B
dist_client_...dev.js gzip 318 B 318 B
dist_client_...dev.js gzip 317 B 317 B
pages-api-tu...dev.js gzip 43.5 kB 43.5 kB
pages-api-tu..prod.js gzip 33.1 kB 33.1 kB
pages-api.ru...dev.js gzip 43.4 kB 43.4 kB
pages-api.ru..prod.js gzip 33.1 kB 33.1 kB
pages-turbo....dev.js gzip 52.9 kB 52.9 kB
pages-turbo...prod.js gzip 38.7 kB 38.7 kB
pages.runtim...dev.js gzip 52.8 kB 52.8 kB
pages.runtim..prod.js gzip 38.7 kB 38.7 kB
server.runti..prod.js gzip 62.5 kB 62.5 kB
Total 2.98 MB 2.98 MB ⚠️ +4 B
📎 Tarball URL
https://vercel-packages.vercel.app/next/commits/2b37d21333dd7d2d2e04779712bd4fc51176e495/next

- Add #[allow(dead_code)] to ProjectInstance::remote field and is_remote()
  method, which are scaffolded for future daemon dispatch wiring
- Remove two needless &-borrows on project.ctx() calls (clippy::needless_borrow)
- Update next-server-nft inline snapshot to include multi-project.js, which
  is now compiled into dist/lib/ and correctly traced by standalone output

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

created-by: Turbopack team PRs by the Turbopack team. tests Turbopack Related to Turbopack with Next.js. type: next

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants