---
date: 2026-05-10
type: ERR
scope: agent-pool / frontend / package.json
status: 沉淀，未修复（workaround 已生效）
---

# pool slot 的前端启动忽略 FRONTEND_PORT，全部回退到 3000（多 slot 同跑必撞）

## 现象

slot-2 claim 后跑 `cd frontend && npm run dev`，日志显示监听 `localhost:3000`，
不是 slot-2 应有的 3600。`ss -tlnp` 也确认是 3000。

## 根因（双层）

**第一层**：`frontend/package.json` 的 dev 脚本是

```json
"dev": "next dev -p ${PORT:-3000} -H 0.0.0.0"
```

`${PORT:-3000}` 是 **shell expansion**，发生在 npm run 启动 next 之前，**不会**读
`.env`（dotenv 加载发生在 Next.js 进程内部）。所以 shell 里 `PORT` 没值，直接 fallback 到 3000。

**第二层**：池脚本写出来的所有 slot `.env` 里的 `PORT` 是同一个 hardcode 值 `3101`，
跟各 slot 的 FRONTEND_PORT 完全不匹配：

```
slot-1: PORT=3101  FRONTEND_PORT=3300
slot-2: PORT=3101  FRONTEND_PORT=3600
slot-3: PORT=3101  FRONTEND_PORT=3700
slot-4: PORT=3101  FRONTEND_PORT=4200
```

即便 dotenv 加载了 `.env`，PORT 也是错的（3101 不对应任何 slot）。

## 影响

**多个 slot 同时起前端会全部抢 3000，第二个起来的 EADDRINUSE 失败**——这是池"4 个 slot
并行"承诺的硬伤。Caddy 的 `slot-N.chentao.test.jiachentao.com` 反代 3300/3600/3700/4200，
所以 Caddy 域名对前端**完全失效**（除了 slot-1 抢到 3000 那种巧合，且即便如此 Caddy 也代到错端口）。

后端没问题：NestJS 是进程内 dotenv 读 `process.env.BACKEND_PORT`，能正确拿到 3601 / 3701 等。

## 临时修复（每个 slot 跑前端时显式 export PORT）

```bash
PORT=$FRONTEND_PORT npm run dev
# 或具体端口
PORT=3600 npm run dev
```

本 session 验证通过：`PORT=3600 npm run dev` 后 Next.js 监听 3600，Caddy `slot-2.chentao.test.jiachentao.com` 通。

## 永久修复（待做，建议方向）

三选一：

1. **改 `frontend/package.json`**：
   ```json
   "dev": "next dev -p ${PORT:-${FRONTEND_PORT:-3000}} -H 0.0.0.0"
   ```
   shell 里 FRONTEND_PORT 也得 export。或更稳：
   ```json
   "dev": "dotenv -e .env -- next dev -H 0.0.0.0"
   ```
   配合 next.config 用 `process.env.FRONTEND_PORT`（next 16 不直接吃 next dev 的 port option from env，得改启动方式）。

2. **改池脚本**：`pool-init` / `setup-worktree.sh` 写 `.env` 时 `PORT=$FRONTEND_PORT`
   而不是 `PORT=3101`。最小改动，但治标——前提是 dotenv 实际能影响 shell expansion，
   要确认 `npm run dev` 是否能读到 `.env`（一般需要 `dotenv -e .env --` 包一层）。

3. **claim 脚本 export PORT**：`agent-claim.sh` 的 export 行加一条 `export PORT=$FRONTEND_PORT`，
   AI 用 eval 后 PORT 就在 shell 里了，npm run dev 自然拿到。**这条最简洁**，只改一处。

推荐 (3)：claim 脚本 export 行加 `export PORT=$FRONTEND_PORT`，命名也对得上 next 的约定。

## 触发条件

- pool slot claim 后跑前端
- 不指定 PORT 显式 export

## 关联

- pool-pin-codeworkspace 已 merge (#285)，该 PR 没改这个
- ERR-20260510-002（pre-push 缺 testing/deps）也是池脚本类问题，建议跟 003 一起修
