Codex 环境初始化失败:6 个原因 + setup.sh 模板

setup 脚本还没跑到 task 就挂了——通常是 Node/Python 版本不匹配、私有 registry 没 token、安装超过 sandbox 超时。

你给 Codex 派一个 task,它卡在 “Setting up environment” 永远过不去。日志里要么是 npm ERR! 401 Unauthorized,要么 python: command not found,要么 10 分钟挂机最后报 Setup timed out。Codex 根本没读到你的代码,没出 plan——sandbox 连 pnpm install 都没跑到。

Sandbox 跑的是极简 base image + 你的 setup.sh(或 .codex/setup.sh)。绝大多数 setup 失败是六类原因之一:运行时版本不对、私有 registry 缺 token、装得太慢、缺原生编译依赖、缺系统包、setup 脚本静默失败。下面拆解每类怎么识别,加一份能解决 90% 项目的 setup 模板。

常见原因

按命中率从高到低:

1. 项目的 Node/Python 版本和 Codex base image 不匹配

Codex sandbox 一般是 Node 20 + Python 3.11。你的项目要 Node 18(lockfile 是它生成的)或 Python 3.12(用了 match 语法),npm install 报 engine 不匹配,或者 import 直接崩。

如何判断:日志里搜 EBADENGINEUnsupported engineSyntaxError: invalid syntax(Python)、requires: node@<version>。setup 脚本开头加一行 node -v && python --version,版本错了一眼看出来。

2. 私有 npm / pip registry 缺 token

你的 package.json 从 GitHub Packages 或 Verdaccio 拉 @your-org/private-pkg。Codex 没有 .npmrc token,npm install 直接 401 Unauthorized

如何判断:setup 日志搜 401403UnauthorizedNot Found,配上你的 registry URL。失败的包名以 @your-org/ 开头就是这个原因。

3. 安装超过 sandbox 超时

Codex sandbox 有 setup 超时(一般 5-10 分钟)。大 monorepo 冷装 pnpm install,或者为 Playwright 拉 500MB Docker base,会直接撞上限。

如何判断:日志结尾是 timeout 而不是某个具体包报错。本地同样安装如果冷启动要 >5 分钟,sandbox 必撞超时。

4. 原生编译依赖缺

node-gypsharpnode-canvaslxmlpillowpsycopg2-binary 需要 gccpython-devlibpq-dev 等系统包。Codex base image 很瘦,这些默认不装。

如何判断:搜 gcc: command not foundPython.h: No such filepg_config: command not found,或者 node-gyp 的 stack。原生编译失败往往日志一长串,但越过前 50 行就清楚。

5. Setup 脚本失败后静默继续

你的 setup.sh 写的是 npm install && npm run build。install 部分成功(有 warning 但没 error),脚本继续往下,build 在某个莫名其妙的地方挂掉——其实根因是上一步。

如何判断:日志里第一个 error 不是根因。脚本顶部加 set -euo pipefail 重跑,真正的错就浮出来。

6. 出站网络被限或被禁

Codex sandbox 限制出站流量。某些 registry(公司 VPN 内自建的那种)根本访问不到,GitHub raw 下载可能被限速。

如何判断getaddrinfo ENOTFOUNDconnect ECONNREFUSED、或某个非公网域名的 503 Service Unavailable。换个网络试同 URL——能通就是 sandbox 出站被限。

最短修复路径

按收益从高到低。前 3 步覆盖”版本 / token / 原生依赖”三大件。

Step 1:固定运行时版本,让 Codex 能识别

repo 根加:

# .nvmrc
20.11.0

# .python-version
3.11.7

Codex sandbox 会自动检测、nvm use / pyenv install 切到指定版本再 npm install。要别的版本就改这里。

Bun / Deno / Java 同理:.bun-versiondeno.json.java-version

Step 2:写一个 fail-fast 的 setup.sh

.codex/setup.sh(或 Codex 配置指定的位置):

#!/usr/bin/env bash
set -euo pipefail   # 首错即停 / 禁未定义变量 / pipe 失败也停

echo "=== Runtime versions ==="
node -v
python --version || echo "python not present"

echo "=== System deps ==="
which gcc make pkg-config || true

echo "=== Install ==="
# 用 ci 不用 install——确定性 + 更快
npm ci --no-audit --no-fund

echo "=== Build ==="
npm run build --if-present

echo "=== Setup done ==="

set -euo pipefail 这行最关键——脚本会在首个错误处停下,而不是级联错下去把你绕晕。

Step 3:把 registry token 放进 Codex secrets

私有 npm 包:

  1. 在 registry 生成只读 token(GitHub Packages 的话是 PAT + read:packages 权限)。
  2. Codex 设置 → Secrets 加 NPM_TOKEN=ghp_xxx
  3. setup.sh 里从 env 生成 .npmrc
cat > ~/.npmrc <<EOF
@your-org:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
always-auth=true
EOF

pip:

export PIP_INDEX_URL="https://${PYPI_USER}:${PYPI_TOKEN}@pypi.your-org.com/simple/"
pip install -r requirements.txt

绝对不要 commit .npmrc / .pip.conf——只从 env 生成。

Step 4:原生编译依赖提前装

package.json 里有 sharpcanvasbcryptnode-gyp 系列就先装构建工具:

# Ubuntu / Debian base(Codex sandbox 多数是这个)
apt-get update -qq
apt-get install -y --no-install-recommends \
  build-essential \
  python3-dev \
  libpq-dev \
  libcairo2-dev libjpeg-dev libpango1.0-dev libgif-dev \
  libvips-dev   # sharp 需要

Python 的 psycopg2lxmlpillowlibpq-devlibxml2-devlibjpeg-dev

能换预编译版本就换(sharp--platform=linux --arch=x64 标志,psycopg2psycopg2-binary),直接跳过原生编译。

Step 5:让 install 更快,避开超时

npm install 换成 npm ci(跳过依赖解析、更快 + 确定)。pnpm / yarn 同理:

# pnpm
pnpm install --frozen-lockfile --prefer-offline

# yarn
yarn install --frozen-lockfile --offline-mirror=.npm-offline

Monorepo 就只装 task 涉及的那块:

# pnpm workspace,只 build API 包
pnpm --filter=@your-org/api install

harness 支持的话把 node_modules 缓存——首次慢、之后秒级。

Step 6:本地先验证 setup,再派 task

别在 Codex 日志里调环境问题,本地复现一遍:

docker run --rm -it -v $(pwd):/repo -w /repo node:20-bookworm bash
# 容器里:
bash .codex/setup.sh

容器里跑通 sandbox 也能通(前提是 secrets 配齐了)。本地都跑不通,就在本地全工具链下修,比对着 Codex 的 setup-only 日志省一万倍精力。

预防建议

  • 永远在 .nvmrc / .python-version 里固定运行时版本——不要赌 sandbox 猜得对
  • 每个 setup.sh 顶部加 set -euo pipefail,让失败 loud 不要 silent
  • registry token 走 Codex secrets,setup.sh 里从 env 生成 .npmrc,绝不 commit
  • 原生依赖优先用预编译(sharppsycopg2-binary),别让 sandbox 跑源码编译
  • npm ci / pnpm install --frozen-lockfile——更快、确定、严格按 lockfile
  • 派 task 前先在干净 Docker 容器里跑通 setup 脚本
  • setup 控制在 3 分钟内,给 sandbox 超时留余量

相关阅读

标签: #Codex #排查 #环境 #CI #依赖