Skip to content

Worktree verify cannot run a Next.js build: Turbopack rejects a symlinked node_modules #160

Description

@rbinar

What happened

Delegating a change that touches a Next.js app and gating it with the project's own
./check.sh is not possible today, because the check runs a production build and the build
dies before it starts:

Error [TurbopackInternalError]: Symlink [project]/node_modules is invalid, it points out of the filesystem root

Why the symlink is there

A cli-dispatch worktree contains only tracked files. node_modules is gitignored, so a
fresh worktree has none, and installing two full dependency trees per delegated run is not a
reasonable cost for a verify step. The obvious workaround — symlink them from the main
checkout — is what Turbopack refuses.

Same class of problem, different cause, for gitignored env files: without backend/.env the
app refused to boot and --verify reported FAIL for a change that was fine. That one IS
solvable by linking, and I did. The Turbopack one is not solvable that way at all.

Impact

--verify is structurally limited to the non-frontend part of a repo's checks whenever the
project builds with Turbopack. Two runs in one session came back exit 3 (verify failed) for
reasons that had nothing to do with the worker's diff, which is the failure mode --verify
exists to prevent — a FAIL you have to investigate and then discard costs more than no gate.

Workaround in use

Two wrappers: one links .venv / .env / node_modules and runs the full gate (works for
backend-only repos), one skips the frontend build entirely and runs lint + the backend suite.
The orchestrator then runs the real full gate in the main checkout before committing. That
works, but it means the runner's verdict is not the whole gate and the human has to know that.

Possible directions

  • Copy (or hardlink) node_modules instead of symlinking when the target is inside the same
    filesystem — costs disk and setup time, but only for repos that need it.
  • A documented --verify-setup hook so a project can declare how to make a worktree runnable,
    instead of every user rediscovering this.
  • At minimum: mention the Turbopack limitation in the runner docs, so the next person reads it
    instead of measuring it.

Measured 2026-08-21 with Turbopack v16.2.11, cli-dispatch 4.27.0, backend cx.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions