# Next.js 16 在 worktree 启动失败的真相（修正归因）

> **日期**: 2026-04-13（初版）→ 2026-04-14（修正）
> **场景**: worktree 中启动 Next.js 16 dev server / build
> **错误码**: [ERR-20260413-002]（修正归因，已不是同一个根因）

## 🔴 重要：原归因错误

**原结论（错误）**："Turbopack 的 filesystem root 解析与 git worktree 不兼容。"

**实际上 Turbopack 和 worktree 完全没有任何冲突。** 之所以表现出"在 worktree 里 `next dev` 静默 exit(0)"，是两个**完全无关**的 bug 同时命中导致的假象。一旦两个 bug 都修好，worktree 里 Next.js 16 + Turbopack 正常运行。

## 真正的根因（两个独立问题）

### 根因 A：`@next/swc-linux-x64-gnu.node` 二进制被截断

```bash
$ file node_modules/@next/swc-linux-x64-gnu/next-swc.linux-x64-gnu.node
ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked,
missing section headers at 137836944
```

- 文件实际大小 28MB，但 ELF header 声称 section headers 位置在约 138MB
- Node 通过 `require()` 加载原生模块时 `mmap` 这个 ELF
- 访问超出文件末尾的映射页时内核发 **SIGBUS**
- `next dev`: SIGBUS 被 Node 捕获后静默 exit(0)，没有任何 stderr 输出，看起来像"启动后立即退出"
- `next build`: 直接 `Bus error (core dumped)`，退出码 135 (128+7)
- `next info`: 同样 `Bus error` —— 这是关键诊断信号，`next info` 根本不碰 Turbopack

**修复**：重装 `@next/swc-*` 包：
```bash
rm -rf node_modules/@next/swc-linux-x64-gnu node_modules/@next/swc-linux-x64-musl
npm install
```
修复后 `file` 显示正常的 "stripped"，文件大小恢复到 ~138MB。

### 根因 B：`next.config.ts` 用 `import.meta.url` 触发 ESM/CJS 混编

修掉 swc 后第二个错误浮现：

```
Unhandled Rejection: ReferenceError: exports is not defined in ES module scope
    at <unknown> (next.config.compiled.js:2:23)
```

原 `next.config.ts`：
```ts
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
outputFileTracingRoot: path.join(__dirname, '../'),
```

Next 16 把 `next.config.ts` 编译成 `next.config.compiled.js`，但该文件产物混用了 CJS `exports.X = ...` 和 ESM 加载，运行时抛错。

**修复**：用 `process.cwd()` 替代 `import.meta.url`。`next dev` 运行时 cwd 正好是 frontend 目录：
```ts
outputFileTracingRoot: path.join(process.cwd(), '../'),
```

## 诊断流程（下次用）

当 `next dev` 静默退出时：
1. 先跑 `npx next info` —— 它不需要 Turbopack，纯 Node。如果也 Bus error 或静默退出，就是 swc 二进制问题
2. `file node_modules/@next/swc-*/next-swc.*.node` —— 正常应该 stripped + ~138MB，异常会有 "missing section headers"
3. 如果 swc 正常但 dev 还挂，删掉 `next.config.ts` 里所有 ESM-only 特性（`import.meta.url`、top-level await 等），改用 `process.cwd()`

## 教训

- **"X 不兼容 Y"是一个危险的归因**，特别是当 Y（worktree）是很常见的环境时。先穷举更低成本的解释（文件损坏、配置错误）。
- **在归因为"上游 bug"前，至少验证一条替代假说**。本案如果早跑 `file *.node` 或 `npx next info`，5 秒就能定位。
- 原文档写了一堆"尝试过但无效的方案"（turbopack.root、`--webpack`、setsid、nohup…）全是在 B 路线下绕路，因为 A 的问题被完全忽略了。
