跳转到内容

退出码契约

mailagent 的退出码是契约的一部分——agent 不该靠解析文本判断成败,而该靠退出码 + status 字段。本页是全表 + 脚本化判定手册。

退出码含义对应 error.code触发场景
0成功业务正常(含 partial_failure 但 0 失败的情况)
1业务失败(非 batch)E_NOT_FOUND / E_INTERNAL / E_LLM_FAILEDnot found / Notion API 错 / dry-run 检测到不一致 / 内部异常兜底
2参数错E_INVALID_ARG / E_NOT_IMPLEMENTEDflag 非法 / 互斥 / 范围超出 / typer 自动校验失败
4认证失败E_AUTH_FAILED写命令缺 MAILAGENT_CLI_API_KEY 或 token 不匹配
5数据不一致E_SCHEMA_MISMATCHdb_version != expected / 读到不兼容 schema
6partial_failureE_PARTIAL_FAILUREbatch 命令同时有 succeeded 和 failed,未熔断
7abortedE_ABORTEDSIGINT / SIGTERM 第一次(当前 unit 跑完后退出)
8max-failures 熔断E_MAX_FAILURES长任务连续失败超 --max-failures
9pm2 conflictE_PM2_RUNNING写命令检测到 PM2 mail-sync 正 online
130SIGINT 二次强退—(直接 sys.exit(130)在 abort summary 阶段再按 Ctrl-C
Terminal window
mailagent -o json email resync --range 53000-53100 --replace-existing
rc=$?
case "$rc" in
0) echo "all resynced" ;;
1) echo "business failure (not found / notion error)"; exit 1 ;;
2) echo "bad args — fix the command line"; exit 2 ;;
4) echo "auth failed — set MAILAGENT_CLI_API_KEY"; exit 4 ;;
5) echo "db schema mismatch — run backend migration first"; exit 5 ;;
6) echo "partial failure — inspect data.failed[], re-run failed ids"; ;;
7) echo "aborted by SIGINT — resume with --resume-from"; ;;
8) echo "circuit-broken by --max-failures — backend likely unhealthy"; exit 8 ;;
9) echo "pm2 mail-sync running — stop it or pass --allow-concurrent"; exit 9 ;;
130) echo "force-quit"; exit 130 ;;
*) echo "unexpected rc=$rc"; exit "$rc" ;;
esac

各码的标准处理动作:

  • 0 —— 成功。注意 batch 命令若全部 unit 成功(哪怕 statussuccess)退 0
  • 1 —— 单封 / 非 batch 的业务失败。解析 error.code 区分 not-found(可忽略)vs LLM 失败(可重试)。
  • 2 —— 你的命令行写错了。不要重试,先修命令。
  • 4 —— 鉴权。检查 MAILAGENT_CLI_API_KEY 是否注入。详见 鉴权契约
  • 5 —— DB schema 不一致。先让后端起 DB 迁移,再重跑 CLI。不要硬重试
  • 6 —— 部分成功。从 data.failed[].internal_id 收集失败 id,单独重跑那一批。详见下文。
  • 7 —— 被 SIGINT 优雅中止。用 --resume-from <N> 从断点续跑(checkpoint)。详见 长任务契约
  • 8 —— 连续失败触发熔断,通常意味着后端 / 网关整体出问题。先排障,别盲目重试
  • 9 —— PM2 mail-sync 在跑,写命令为防双写自动拒绝。停 pm2 或显式 --allow-concurrent。详见 长任务契约
  • 130 —— 二次 Ctrl-C 强退,可能没来得及写 checkpoint / 打 summary。

这是 agent 最常踩的坑:

  • exit 1E_NOT_FOUND 等)= 非 batch 模式的业务失败。 例如 email get 99999(单封、不存在)退 1,输出是 status: "error" 的 wrapper,没有 data
  • exit 6E_PARTIAL_FAILURE)= batch 模式下”有成功也有失败”。 例如 email resync --range 53000-53100 里 87 封成功 13 封失败,退 6,输出是 status: "partial_failure" 的 wrapper,data.succeeded / data.failed / data.summary 都在

换句话说:

exit 1exit 6
模式单封 / 非 batchbatch(--range / --ids
status"error""partial_failure"
data否(只有 error是(succeeded/failed/summary
重试策略整条命令重试或放弃只重跑 data.failed[] 里的 id
Terminal window
# exit 6 的标准处理:抽出失败 id,逐个或成批重跑
out=$(mailagent -o json email resync --range 53000-53100 --replace-existing)
if [ $? -eq 6 ]; then
failed_ids=$(jq -r '.data.failed[].internal_id' <<<"$out" | paste -sd, -)
echo "retrying failed: $failed_ids" >&2
mailagent -o json email resync --ids "$failed_ids" --replace-existing
fi