vercel / vercel/next.js

Turbopack dev livelocks on darwin-arm64 (pnpm workspace): 603% CPU, never serves a request — unfixed on every stable through 16.3.2, fixed in canary by #96808

Open
#97,850 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Turbopack
Dominant language
JavaScript
Stars
142k
Forks
32.4k
Avg merge
2d 14h
Merged PRs (30d)
351

Description

Turbopack dev-server livelocks on darwin-arm64 in pnpm workspace monorepos — tokio workers spin on the turbo-tasks scheduler queue lock; 603–777% CPU, never serves a request. Regression still alive on every stable since 16.2.6; fixed only in canary by #96808.

This is the same bug reported in #95798, which was auto-closed by the stale-issue bot for lacking a public repro link and is now locked. No code in any stable release (through 16.3.2) fixes it.

Link to the code that reproduces this issue

https://github.com/koding88/repro-turbo-livelock

To Reproduce
  1. On macOS Apple Silicon, clone the repro repo above.
  2. Run pnpm install, then pnpm exec turbo run dev (which runs next dev --turbo -p 3137).
  3. next-server prints ✓ Ready in ~250ms and then immediately climbs to 603–777% CPU (6–8 cores) within ~30s, with RSS growing 858 MB → 3.5 GB over 2 min.
  4. curl http://localhost:3137/ hangs to any client timeout → HTTP 000. No Compiling / line, no error, no timeout — the server never serves a single request.

Note: the livelock is sensitive to module-graph depth. A smaller toy workspace does not trigger it. If this 5-package repro does not trigger on your machine, the sample profile + bisect table below confirm the bug is real and fixed by #96808. I can provide a larger repro if needed.

Current vs. Expected behavior

Current: next-server livelocks — 11 tokio-runtime-worker threads spin 100% inside next-swc.darwin-arm64.node, contending on the turbo-tasks scheduler queue lock. The dev server accepts TCP connections but never compiles or responds.

Expected: next-server idles at ~0% CPU when no request is in flight, and serves GET / in a couple of seconds on first compile.

sample profile of the stuck next-server (10s, 6300 samples)
6300 Thread_*: tokio-runtime-worker            ← 11 threads, all 100% busy
+ 6299 ???  (in next-swc.darwin-arm64.node)
  + 2909 _pthread_cond_wait                    ← scheduler queue-lock / condvar contention
  + 1600 active SWC frames (no forward progress)

6300 Thread_*: notify-rs fsevents loop         ← idle (6248/6300 in mach_msg2_trap)
6300 Thread_*: libuv-worker (×4)               ← idle (100% in uv_cond_wait)

The file watcher and libuv pool are idle — this is not an FSEvents problem. It matches #95798's "tokio workers stuck at the same address" exactly: a turbo-tasks scheduler spin, not a compile task making progress. No JS frames are involved.

Bisect by version — the fix is PR #96808, canary-only

Same project, cold .next cache, identical command (next dev --turbo):

stage next@16.2.11 (stable) next@16.4.0-canary.6 (canary, post #96808)
idle, 60s after Ready 603% → 777% CPU, RSS 858 MB → 3.5 GB 0% CPU, 356 MB
GET / (cold compile) hangs → HTTP 000 (15s timeout) HTTP 200 in 1.97s
10s after request still 777% (never recovers) 0% CPU, compile complete

PR #96808 "turbo-tasks: execute scheduled tasks inline when they are read" (merged 2026-08-24) is the fix — it directly addresses the "most contended lock in the system" visible in the profile: a read of a scheduled task now executes it inline instead of contending for the queue, and a read of an in-progress task waits on the task's completion event instead of re-acquiring the queue lock. canary.6 (released 2026-08-24 23:55, after the merge) contains it; canary.3 (2026-08-23, before the merge) does not.

Release timeline — every stable is affected
version released has #96808?
16.2.6 (first reported)
16.2.11 2026-07-21
16.3.0 2026-08-03
16.3.2 (latest stable) 2026-08-21
16.4.0-canary.6 2026-08-24

So upgrading to the latest stable (16.3.2) does not help — users hitting this should either use --webpack or pin next@16.4.0-canary.6 until the fix ships in a stable.

Workarounds
  • next dev --webpack — confirmed 0% CPU idle on the same project.
  • pin next@16.4.0-canary.6.
Provide environment information
Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin 25.5.0 (macOS 26.5)
Binaries:
  Node: v24.14.0
  pnpm: 11.20.0
Relevant Packages:
  next: 16.2.11
  react: 19.2.4
  react-dom: 19.2.4
  turbo: 2.10.11
Next.js Config:
  output: N/A (dev)
  turbopack: root inferred from pnpm-workspace.yaml
Which area(s) are affected? (Select all that apply)

Turbopack

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context
  • Trigger appears to be pnpm workspace + Turbopack + darwin-arm64, not project-specific code (Ubuntu was reported immune in #95798).
  • #95798 was closed by the stale bot's "no valid reproduction link" rule and is now locked, so the regression has nowhere to be tracked.
  • I have also posted this finding as a comment on PR #96808 asking about a stable backport.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked repro repository and reproduce the failure using pnpm install followed by pnpm exec turbo run dev on darwin-arm64. Read PR #96808 and compare stable 16.3.2 with canary.6; the work is complete when the affected stable release serves GET / without the CPU or memory livelock.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, next.js
Domain
build-system, devtools, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.