---
title: "CLI Agent 高频问题排查"
wiki: cli
category: "最佳实践"
slug: troubleshooting-cli-agents
url: https://learnagent.wiki/cli/cards/troubleshooting-cli-agents
tags: ["排错", "故障", "troubleshooting", "Claude Code", "经验"]
last_updated: 2026-04-22
reading_time: 13
---

> 跑过一段时间 Claude Code、Codex CLI、Gemini CLI 之后，你会发现一件事：**CLI Agent 的报错和普通命令行工具的报错是两种生物**。一条 `git status` 出错，问题大概率就在 git 自己；但一条 `claude` 卡住几十秒不动，原因可能在网络、可能在订阅状态、可能在某个挂着的 MCP server，也可能是你昨天写的 PreToolUse hook 进入了死循环。**Agent 是一条长链路**，链路上任何一段坏掉都会让你看到一个含糊的"卡住""超时""报错"。

# CLI Agent 高频问题排查

## 基础概念

跑过一段时间 Claude Code、Codex CLI、Gemini CLI 之后，你会发现一件事：**CLI Agent 的报错和普通命令行工具的报错是两种生物**。一条 `git status` 出错，问题大概率就在 git 自己；但一条 `claude` 卡住几十秒不动，原因可能在网络、可能在订阅状态、可能在某个挂着的 MCP server，也可能是你昨天写的 PreToolUse hook 进入了死循环。**Agent 是一条长链路**，链路上任何一段坏掉都会让你看到一个含糊的"卡住""超时""报错"。

要把排错做高效，得先建立分层定位的思维。一次失败的 Agent 调用，按照"从外到内、从便宜到昂贵"的顺序去查，效率最高：

```mermaid
flowchart TD
    Start([Agent 报错或卡住]) --> L1{1. 网络层<br/>能否 curl 到 API}
    L1 -->|否| Fix1[查代理 / 证书 / DNS<br/>HTTPS_PROXY / NODE_EXTRA_CA_CERTS]
    L1 -->|是| L2{2. 认证层<br/>/status 显示哪条 credential}
    L2 -->|错的 key 或未登录| Fix2[unset ANTHROPIC_API_KEY<br/>/logout 后重新 /login]
    L2 -->|对的| L3{3. 配额层<br/>是否 429 / session limit}
    L3 -->|是| Fix3[切模型 / 等重置 / 降并发<br/>CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY]
    L3 -->|否| L4{4. 上下文层<br/>/context 是否接近上限}
    L4 -->|是| Fix4[/compact 或 /clear<br/>关掉用不到的 MCP server]
    L4 -->|否| L5{5. Agent 自身层<br/>hook / MCP / 工具卡死}
    L5 --> Fix5[claude doctor<br/>检查 hook、MCP、设置文件]

    style Fix1 fill:#fee
    style Fix2 fill:#fef
    style Fix3 fill:#ffe
    style Fix4 fill:#efe
    style Fix5 fill:#eef
```

把这五层记牢，**遇到任何"Agent 不对劲"先按顺序往下走**，能避免 80% 的盲目重装、盲目重启、盲目改配置。

### 核心要素

| 要素 | 说明 |
|------|------|
| **分层定位** | 网络 → 认证 → 配额 → 上下文 → Agent 自身，由外到内排查 |
| **诊断命令** | `claude doctor` / `/status` / `/context` / `/doctor` 是 Claude Code 内置体检入口；`gemini --debug` / `RUST_LOG=debug codex` 是 Gemini / Codex CLI 的对应入口 |
| **可重现最小用例** | 报 bug 前先把环境变量、模型、prompt 缩到最小，区分"我的环境问题"和"工具 bug" |
| **日志位置** | Codex CLI 写 `~/.codex/logs/codex-tui-*.log`；Claude Code 用 `/feedback` 自动带 transcript；Gemini CLI 通过 `--debug` 输出到 stderr |
| **回滚而非重装** | 配置类问题重装基本无效，优先 `/rewind`、`/clear`、注释掉新加的 hook，再决定是否动安装 |

## 基础用法

### 故障速查表

下面这张表覆盖 Claude Code / Codex CLI / Gemini CLI 在 2026 年 4 月之前最常见的 12 类报错。出问题先来这里查一遍，**90% 的情况能直接拿到处置方法**。

| # | 典型表现 / 报错 | 一眼定位 | 修复方法 |
|:-:|---|---|---|
| 1 | `command not found: claude` | PATH 里没有 `~/.local/bin` | `echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc` |
| 2 | `npm install -g` 报 `EACCES: permission denied` | 全局目录归 root 所有 | **不要用 sudo**。改用官方 `curl -fsSL https://claude.ai/install.sh \| bash`，或 `npm config set prefix '~/.npm-global'` |
| 3 | `Killed` during install on Linux | 内存不足，OOM killer 干掉了安装进程 | 加 2G swap：`sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile` |
| 4 | `unable to get local issuer certificate` / `SELF_SIGNED_CERT_IN_CHAIN` | 公司代理在做 TLS 检查，Node 不认它的根证书 | `export NODE_EXTRA_CA_CERTS=/path/to/corp-ca.pem`，必要时加 `NODE_OPTIONS="--use-openssl-ca"` |
| 5 | `API Error: 401` / `Invalid API key` / OAuth token expired | 旧的 `ANTHROPIC_API_KEY` 抢了 OAuth | `unset ANTHROPIC_API_KEY` 后 `/logout && /login`；用 `/status` 确认当前生效的 credential |
| 6 | `API Error: 403 Forbidden` 登录后 | 订阅过期 / 公司账号没分到 Claude Code 角色 / 代理挡了 | 查 [claude.ai/settings](https://claude.ai/settings)；公司账号找 admin 加角色；代理场景去 `/en/network-config` 查白名单 |
| 7 | `API Error: 429 · Rate limited` 或 `You've hit your session limit` | 撞到模型限流或订阅周限额 | `/status` 看 credential 是不是订阅；`/model` 切到更小模型；降并发 `CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY=2`；等 `/usage` 显示的重置时间 |
| 8 | `Prompt is too long` / `Autocompact is thrashing` | 上下文窗口塞满，自动压缩失败 | `/context` 看占用；`/compact keep only the plan and the diff` 带焦点压缩；关闭未用的 `/mcp disable <name>`；上下文已塞死就 `/clear` |
| 9 | `API Error: 529 Overloaded` | 该模型全局过载，已自动重试到上限 | `/model` 切到不同模型（容量分模型计算）；隔几分钟再试；查 [status.claude.com](https://status.claude.com) |
| 10 | MCP server 启动后"沉默失败"，工具列表里没有 | 路径含空格 / 启动慢被 60s 默认超时 / config 没装载 | `claude doctor` 看 MCP 报错；用 `claude mcp add -s user <name> <cmd>` 重加；长启动设 `MCP_TIMEOUT=120000` |
| 11 | Stop hook 死循环，Agent 反复"再试一次" | Stop hook 没看 `stop_hook_active` 字段 | 在 hook 脚本头部加 guard：`[ "$(jq -r '.stop_hook_active // false')" = "true" ] && exit 0`；卡住时 Ctrl+C 两次或 `kill -9` 当前 claude 进程 |
| 12 | `API Error: 400 due to tool use concurrency issues` | tool_use / tool_result / thinking 块顺序错乱 | `/rewind` 或 Esc 两下回到上一个 checkpoint，从那里继续 |

### 三段最常用的"急救代码"

**急救 1：突然 401 / 403，先确认到底用的哪条 credential。**

```bash
# 在出错的同一个 shell 里跑，看 ANTHROPIC_API_KEY 是否被某个 .env / 旧 zshrc 偷偷设了
env | grep ANTHROPIC

# 如果看到一行 ANTHROPIC_API_KEY=sk-... 但你本意是用订阅，就清掉
unset ANTHROPIC_API_KEY

# 重新登录 + 在 Claude Code 内核对
claude
> /status        # 看 Active credential 是 OAuth (Pro/Max) 还是 API key
> /logout
> /login
```

**急救 2：429 / context too long 同时出现，说明上下文撑爆了 + 在硬撞限流。**

```bash
# 在 claude 会话里
/context           # 先看哪一块占大头：system / tools / memory / messages
/mcp              # 列出当前挂载的 MCP，哪些其实这次任务用不到
/mcp disable obsidian   # 用不到的先停，工具定义就不会再占 context
/compact keep only the latest plan, diff, and unresolved errors

# 如果还是不行，直接重置
/clear
```

**急救 3：MCP server 死活连不上，开 debug 看真实错误。**

```bash
# Claude Code：内置体检
claude doctor

# 如果 doctor 显示 MCP "configured but failed to start"，
# 把 server 命令拎出来手动跑一遍，看真实 stderr
npx -y @modelcontextprotocol/server-filesystem /Users/me/Desktop

# 启动慢的 server（如要下载模型 / 拉资源）记得抬高超时
export MCP_TIMEOUT=120000
claude

# 如果是 ~/.claude/mcp.json 不被加载，改用 CLI 命令重加（更可靠）
claude mcp add -s user filesystem npx -- -y @modelcontextprotocol/server-filesystem /Users/me/Desktop
```

预期行为：执行 `claude doctor` 后，正常状态会逐项打勾（Installation / Search / MCP / Settings / Auto-update）；任何一项红字基本就是你这次问题的源头。

## 同类工具对比

不同 CLI Agent 的诊断入口不一样，但思路是相通的。下表收束三家最常用的"开 debug、看日志、查健康"的入口，方便互相迁移经验：

| 维度 | Claude Code | OpenAI Codex CLI | Google Gemini CLI |
|------|-------------|------------------|-------------------|
| 体检命令 | `claude doctor` / `/doctor`（内嵌检测安装、Search、MCP、Settings、Auto-update） | 无统一 doctor 命令，靠 `--version` + 日志判断 | 无统一 doctor 命令，issue 模板要求附 `gemini --debug` 输出 |
| 状态命令 | `/status`（看 credential、模型、配额）/ `/usage` / `/context` | 会话内 `/feedback` 收集 Request ID | 通过 `--debug` 输出请求详情 |
| 详细日志开关 | `claude --debug --verbose`（限交互调试时） | `RUST_LOG=debug codex` 或 `RUST_LOG=trace codex`，可加 `RUST_LOG_FORMAT=json` | `gemini --debug "..." 2>&1 \| tee bug.txt` 或 `DEBUG_MODE=1` |
| 日志落盘位置 | 默认不持久化日志，需 `/feedback` 把 transcript 自动打包发回 | `~/.codex/logs/codex-tui-*.log`，自动轮转 | 默认 stderr，无固定文件路径 |
| 上下文压缩 | `/compact`（带焦点参数）/ `/clear` / `/rewind` | `/clear` / `/compact`（视版本） | 重新启动会话或缩短 prompt |
| 限流定位 | `/status` 看 credential，错误信息会写"this may be a temporary capacity issue" | 错误体含 `rate_limit_exceeded`，需自己读 stderr | 报 `You exceeded your current quota`，需查 Google AI Studio 配额面板 |
| 上报方式 | `/feedback` 一键带 transcript 发到 Anthropic（Bedrock/Vertex 不可用） | `/feedback` + Request ID | 需手动开 GitHub issue 附 `--debug` 日志 |

**核心区别用一句话**：

- **Claude Code 把诊断做成了一等公民**——`claude doctor`、`/status`、`/context`、`/usage`、`/feedback` 互相补位，能在 30 秒内把"我哪儿出问题"答出来。
- **Codex CLI 走的是"日志友好"路线**——本地有持久日志可以 `tail -f`、`grep ERROR`，但需要自己拼 `RUST_LOG`，不太适合非工程背景用户。
- **Gemini CLI 当前最薄**——没有 doctor、没有 status、没有持久日志，几乎所有问题都靠 `--debug` 现场抓，所以排错门槛最高。

> 这意味着：**学会 Claude Code 的排错命令，迁移到另两家时只需要换"日志怎么开"这一处**，分层定位的思维和顺序是通用的。

## 常见误区

| 误区 | 准确理解 |
|------|----------|
| 把模型 429 / 529 当成"Agent 卡死"，疯狂 Ctrl+C 重启 | 429 / 529 是 API 层面的限流和过载，**重启 Agent 改变不了限额**。正确动作是 `/status` 确认 credential、`/model` 切模型、降并发或等 `/usage` 显示的重置时间 |
| 看到任何报错都先 `npm install -g` 重装一遍 | 配置类问题（hook 死循环、MCP 没启动、ANTHROPIC_API_KEY 串了、上下文撑爆）**重装一次都解决不了**。先 `claude doctor` + `/status` 才是正确顺序 |
| Stop hook 写了"keep working"，结果 Agent 反复触发陷入死循环却没及时 kill | Stop hook 的输入里有 `stop_hook_active` 字段，**guard 在脚本第一行就要写**：`[ "$(jq -r '.stop_hook_active // false')" = "true" ] && exit 0`。卡住时 Ctrl+C 两次仍不退就 `pkill -9 claude` |
| 用 sudo 解决 npm 全局安装权限问题 | `sudo npm install -g` 会让后续所有更新、卸载、`postinstall` 都需要 sudo，并且引入安全隐患。**官方推荐用原生安装脚本**或 `npm config set prefix '~/.npm-global'` |
| 公司代理报 SSL 错误就直接 `NODE_TLS_REJECT_UNAUTHORIZED=0` | 这等于把整条 Agent ↔ API 的 TLS 校验全关掉，等于裸奔。**正确做法是从 IT 拿 corp-ca.pem，设 `NODE_EXTRA_CA_CERTS`**，TLS 链路依然受信 |
| 觉得 Claude Code 给的报错文字不准就忽略它 | 错误文本里通常带"do this next"的提示，例如 `Run /rewind to recover` / `Press esc twice to go back` / `Run /context`，**照着做一次再判断**，不要看见英文就下意识忽略 |
| 把 MCP server 静默失败误判为"协议有 bug" | 大概率是路径含空格、启动超过 60s 默认超时、config 没生效。**先 `claude doctor` 看 MCP 段落，再把 server 命令手动跑一遍** 验证它本身能起来 |

## 优劣势分析

排错路径有三种：自己按速查表排、直接问 Agent 自己、提工单。三者各有适用场景，混用才是高效姿势。

| 路径 | 优势 | 劣势 |
|------|------|------|
| **自助排错（看速查表 / 文档）** | 10 秒定位高频问题；不消耗 token；不留私域信息外泄 | 需要预先建立"分层定位"的肌肉记忆；遇到全新问题没有线索 |
| **直接问 Agent 自己（在会话里描述报错）** | Agent 知道自己内置的诊断命令，能引导你跑 `/doctor`、`/status`；对常见问题给出修复 patch | 撞到限流 / 401 / 上下文超限时 Agent 本身就答不动；可能编造不存在的命令；transcript 越长越烧 token |
| **提工单 / GitHub issue（`/feedback` 或手动）** | 复杂 bug、版本回归类问题最终只能靠官方查；`/feedback` 自动带 transcript 是最高效的上报姿势 | 周期以天为单位；要把问题缩小到可重现的最小用例；公司账号要小心 transcript 里的代码片段 |

**实际经验上的最优组合**：

1. **第一关自助**：报错出现 → 先去速查表对一眼，5 类高频报错（401 / 429 / context / hook 死循环 / SSL）能直接秒杀。
2. **第二关问 Agent**：自助没命中 → 在会话里把 stderr / `/status` 输出贴回去，让 Agent 引导跑 `claude doctor`、`/context`，70% 的中频问题能解决。
3. **第三关提工单**：以上都不行 → `/feedback` 一键带 transcript 上报；同时 GitHub 搜一下报错关键词，看是不是已知 issue。

切忌一上来就提工单——等回复的时间足够你自己解决三轮问题。

## 思考题

<details>
<summary>初级：你在新机器上跑 <code>claude</code>，提示 <code>API Error: 403 Forbidden</code>。订阅明明是有效的，怎么定位？</summary>

**参考答案：**

按"分层定位"的顺序走：

1. **认证层先看 credential**：在出错的同一个 shell 跑 `env | grep ANTHROPIC`。99% 概率会发现一行 `ANTHROPIC_API_KEY=sk-...` 是从旧 `.zshrc`、旧项目 `.env`、direnv、或公司脚手架里继承下来的。这个 key 可能属于一个早就被禁用的 Console org，于是订阅 OAuth 被它压住，API 直接回 403。
2. **修复**：`unset ANTHROPIC_API_KEY`，并把 `~/.zshrc` / `~/.bashrc` / `~/.profile` 里的 `export ANTHROPIC_API_KEY=...` 行删掉，否则下次重开 shell 又会复发。
3. **核对**：再次 `claude` 进入会话，跑 `/status`，确认 Active credential 显示成你的订阅（OAuth），而不是 API key。
4. **如果还是 403**：那真的是订阅或角色问题——查 [claude.ai/settings](https://claude.ai/settings) 订阅是否过期；公司账号找 admin 确认有没有分到 "Claude Code" 或 "Developer" 角色；公司网络下还要排查代理是否拦截了 OAuth 回调。

整个流程不超过 2 分钟，**关键是不要直接重装 Claude Code，重装解决不了 credential 串台**。

</details>

<details>
<summary>中级：你写了一个 Stop hook 想"如果测试没全过就让 Claude 继续修"，结果 Agent 在终端里疯狂刷屏停不下来，CPU 100%。怎么避免和怎么救场？</summary>

**参考答案：**

**为什么会死循环**：Claude 收到 stop 信号 → 你的 hook 检查测试失败 → 返回 `block` 让 Claude 继续 → Claude 回了一段话又触发 stop → 你的 hook 又 block → 无限循环。

**救场（必须先做）**：

1. 在终端里 Ctrl+C 两次，正常这会中断当前请求；如果 Agent 已经被 hook 牢牢卡住没在请求 API，Ctrl+C 不灵。
2. 另开一个 terminal：`pkill -f claude` 或 `ps aux | grep claude` 拿到 PID 后 `kill -9 <pid>`，把进程一棒打死。
3. 把那个 hook 暂时从 `settings.json` 注释掉再启动 claude，否则一进去又复发。

**正确的写法（避免再次发生）**：在 Stop hook 入口先读 `stop_hook_active` 字段做 guard——如果 Claude 已经因为这个 hook 被 block 过一次了，就让它真的停。

```bash
#!/bin/bash
INPUT=$(cat)
ACTIVE=$(echo "$INPUT" | jq -r '.stop_hook_active // false')

# guard：已经在 stop loop 里了，直接放行
if [ "$ACTIVE" = "true" ]; then
  exit 0
fi

# 真正的检查逻辑：如果测试失败，让 Claude 再修一轮
if ! npm test --silent; then
  echo '{"decision":"block","reason":"tests still failing"}'
  exit 0
fi
exit 0
```

**配套防御**：给所有可能 block 的 hook 设合理的 timeout（默认到点会被 kill 当成非阻塞失败），以及在 settings 里明确写 `"timeout": 30000` 一类的硬上限，防止哪天 hook 自己卡死又拖死 Agent。

</details>

## 参考资料

1. Claude Code 官方 Troubleshooting：<https://code.claude.com/docs/en/troubleshooting>（查询日期 2026-04-22）
2. Claude Code Error Reference（401/403/429/529/context/tool 错误全集）：<https://code.claude.com/docs/en/errors>（查询日期 2026-04-22）
3. Claude Code Hooks 参考与死循环防御：<https://code.claude.com/docs/en/hooks>
4. Claude Code 企业网络与代理配置：<https://code.claude.com/docs/en/network-config>
5. Claude Code GitHub 高频 Issue 列表（看真实社区报错）：<https://github.com/anthropics/claude-code/issues>
6. npm 官方 EACCES 权限问题处理：<https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally>
7. OpenAI Codex CLI 日志位置与 RUST_LOG 调试：<https://developers.openai.com/codex/cli/reference>（查询日期 2026-04-22）
8. Google Gemini CLI 官方 Troubleshooting：<https://google-gemini.github.io/gemini-cli/docs/troubleshooting.html>（查询日期 2026-04-22）

---
*Source: https://learnagent.wiki/cli/cards/troubleshooting-cli-agents*
*Markdown mirror of https://learnagent.wiki, served as text/markdown for LLM ingestion.*