OpenClaw 实战 08|故障排除:Token Mismatch + SSRF 死循环 + "部分存活"假象原创
# 故障排除:Token Mismatch + SSRF 死循环 + "部分存活"假象
这一篇不讲"分布式追踪、日志聚合"那一套通用方法论,只讲 OpenClaw 真实遇到的 3 类典型故障 + 真实定位路径。
本文所有内容都来自
~/.hermes/workspace/blog-material/notes/claude-code/下的 2 条真实故障会话记录(2026-06-22 ~ 2026-06-23):
<session-file>— 浏览器 SSRF 拦截引发的 Telegram 死循环<session-file>— 换模型后 Gateway 假死关键认知:OpenClaw 故障最难的不是定位根因,是分辨"看似活的实际死的"(部分存活假象)。
# §1 那天 Telegram 被轰炸了
今年 6 月某天早上 7 点,我的 Telegram 收到 100+ 条 OpenClaw 消息轰炸——全是同一个失败错误反复重试。
真实场景(来自 <session-file>):
家用 NAS 上跑的 OpenClaw 突然开始疯狂发消息。每条消息都是同一段错误:
browser endpoint blocked by policy
raw_params={"action":"open","url":"https://example.com"}
2
症状:
- Telegram 收件箱被刷屏,几十条/分钟
- Agent 没正确处理这个错误,反复尝试或回复无意义内容
- 服务
systemctl --user status openclaw-gateway.service仍显示active (running),PID 1572847
根因:
Agent 在内部 Task 里试图打开 https://example.com 验证浏览器能力。OpenClaw 的 browser.ssrfPolicy 拦截了 example.com(默认白名单限制)。Agent 没有"优雅失败"逻辑——应该退出当前 Task 改走其他路径,但实际反复重试 + 不断报错,触发 Telegram 频道反复推送。
还有一个隐藏问题:
日志里频繁出现:
[agents/tool-policy] tool policy removed 11 tool(s)
每次 Agent 交互都在重新计算 Tool 权限,11 个 Tool 被频繁移除/添加,严重影响性能且可能导致状态不一致——这是死循环的间接推手。
复盘:
- SSRF policy 拦截(单次故障)
- Agent 不优雅退出(逻辑缺陷)
- Tool Policy 反复重算(性能雪崩)
- Telegram 通道不停推(用户体验灾难)
4 个问题叠加,从"单次拦截"演变成"消息轰炸"。
这个故事揭示了 OpenClaw 故障的 3 个真实特征:
- 症状 ≠ 根因:轰炸只是表象,根因是 Agent 缺少失败处理
- 服务 running ≠ 工作正常:要看应用层日志
- "部分存活"最难诊断:一个通道活着不代表另一个通道活着
下面按这 3 类故障展开。
# §2 OpenClaw 故障的 3 大分类
OpenClaw 故障按"症状 vs 根因"分成 3 类:
| 类别 | 表现 | 根因层级 | 真实案例 |
|---|---|---|---|
| 进程级 | Gateway 进程死了/重启/不响应 | 进程管理(supervisor/systemd)+ 配置生效 | 换模型死掉(拓扑混淆 + Token Mismatch) |
| 行为级 | 进程活着但 Agent 卡死/死循环/输出错乱 | 应用逻辑(Tool 调用、SSRF、Agent 决策) | SSRF 死循环发消息 |
| 幻觉型 | 看上去活着但实际不工作 | 多通道部分存活 | Telegram 降级轮询掩盖 CLI 死亡 |
关键:3 类故障的诊断方法完全不同。
| 类别 | 第一步看 | 第二步看 |
|---|---|---|
| 进程级 | supervisorctl status / systemctl status | supervisorctl tail -f / journalctl |
| 行为级 | OpenClaw 应用层日志 | 行为计数(HTTP 请求/数据库写入) |
| 幻觉型 | 多通道逐一 ping | Token 一致性 / 拓扑定位 |
# §3 第一类故障:进程级 — "换模型死掉"完整路径
最经典的 OpenClaw 故障(来自 <session-file>):
症状:在 OpenClaw 控制面板换了一个模型,Gateway 立刻"死了"——但 supervisorctl status openclaw 仍显示 RUNNING。
# 3.1 拓扑混淆(最常见的前置错误)
我自己维护 3 个 OpenClaw 实例,分布如下:
| 实例 | 部署形态 | SSH 端口 | 进程管理 |
|---|---|---|---|
<aws-instance> 上的 Nova | Docker + Supervisor | 2223 | supervisorctl |
| CasaOS 上的 Hermes | 裸机 + user systemd | 22 | systemctl --user |
| 家用 NAS | 裸机 + user systemd | 22 | systemctl --user |
致命陷阱:<aws-instance> 上的实例走 supervisor 管理,端口 2223。我经常误用 systemd 命令去操作它——systemctl --user status openclaw-gateway 在 <aws-instance> 上当然失败,于是我以为"服务挂了",开始瞎改配置。
铁律(来自素材复用要点):任何 OpenClaw 操作前,先确认拓扑:
# 黄金探测 1:which + systemctl
ssh -p <PORT> <USER>@<IP> "which openclaw; systemctl --user status openclaw-gateway"
# 黄金探测 2:supervisor
ssh -p <PORT> <USER>@<IP> "supervisorctl status openclaw"
# 二选一:
# systemctl 成功 → 裸机 systemd
# supervisor 成功 → 容器 supervisor
# 都成功 → 大概率配置漂移,立即停手排查
2
3
4
5
6
7
8
9
10
# 3.2 PATH 环境变量缺失
SSH 直连 OpenClaw 容器或裸机后,nvm/pnpm 的 bin 目录不会自动加载,openclaw 命令找不到:
# 错:直接跑命令
$ openclaw config get
bash: openclaw: command not found
# 对:显式 export
$ export PATH=/home/<USERNAME>/.nvm/versions/node/v22.20.0/bin:/home/<USERNAME>/.local/share/pnpm/bin:$PATH
$ export HOME=/home/<USERNAME>
$ openclaw config get
__OPENCLAW_REDACTED__
2
3
4
5
6
7
8
9
嵌套 SSH 灾难:
# 错:ssh → docker exec → bash -lc 多层嵌套
# 引号和 ${...} 会被多层 shell 解释
ssh <USER>@<IP> "docker exec <CONTAINER> bash -lc \"openclaw config set ... \${VAR}\""
# 对:先 Base64 编码再远程解码
SCRIPT_B64=$(echo 'openclaw config set gateway.auth.token "${OPENCLAW_GATEWAY_TOKEN}"' | base64 -w0)
ssh <USER>@<IP> "docker exec <CONTAINER> bash -lc 'echo $SCRIPT_B64 | base64 -d | bash'"
2
3
4
5
6
7
复用规则:远程跑 OpenClaw 命令前,永远先 export PATH + export HOME。
# 3.3 Token Mismatch:Gateway 假死的根因
症状链(来自 2026-06-23 换模型死掉):
1. 用户在控制面板换模型
2. OpenClaw 触发配置热重载
3. 重载过程中 Gateway 重新读 Token
4. config 的 Token 和 env 的 Token 不一致
5. Gateway 用 env 的 Token 启动
6. CLI 客户端用 config 的 Token 连接
7. 两边 sha256 不一样 → CLI 报 unauthorized
8. Agent 看上去 "死了"(CLI 完全连不上)
2
3
4
5
6
7
8
但Telegram 通道走降级轮询继续工作——用户从 Telegram 看 Agent 还活着,但实际 CLI 已全挂。这就是 §4 的"部分存活假象" 的来源。
Token 一致性排查(标准动作):
# 1. 读 config 里的 Token(OpenClaw 脱敏了,用 python3 解析)
python3 -c 'import json;print(json.load(open("/home/<USERNAME>/.openclaw/openclaw.json"))["gateway"]["auth"]["token"])'
# 2. 读 env 里的 Token
grep OPENCLAW_GATEWAY_TOKEN /etc/supervisor/conf.d/openclaw.conf
# 或
tr '\0' '\n' < /proc/$(pgrep -f openclaw-gateway)/environ | grep OPENCLAW_GATEWAY_TOKEN
# 3. sha256 比对(不打印明文,避免漏看空格)
HASH_A=$(python3 -c 'import json,hashlib;print(hashlib.sha256(json.load(open("/home/<USERNAME>/.openclaw/openclaw.json"))["gateway"]["auth"]["token"].encode()).hexdigest())')
HASH_B=$(tr '\0' '\n' < /proc/$(pgrep -f openclaw-gateway)/environ | grep OPENCLAW_GATEWAY_TOKEN | sha256sum | awk '{print $1}')
[ "$HASH_A" = "$HASH_B" ] && echo "✅ Token 一致" || echo "❌ Token 不一致"
2
3
4
5
6
7
8
9
10
11
12
13
修复(让 config 跟随 env,单一来源):
openclaw config set gateway.auth.token '${OPENCLAW_GATEWAY_TOKEN}'
supervisorctl reread && supervisorctl update && supervisorctl restart openclaw
# 验证
supervisorctl tail -f openclaw | grep -i 'gateway\|ready'
# 期望看到:[gateway] ready
2
3
4
5
6
# 3.4 配置生效陷阱
改完不重启等于没改:
# 错:以为 reload 就够
openclaw config patch --stdin <<'...'
{ "models.providers.<X>.models": [...] }
...
# 实际:Agent 还是用旧配置
$ openclaw models
(列表里没有新模型)
2
3
4
5
6
7
8
正确流程:
# 1. patch
openclaw config patch --stdin <<'...'
{ ... }
...
# 2. 必须重启
supervisorctl restart openclaw
# 3. 看应用层 ready 日志(不是 Supervisor 状态)
supervisorctl tail -f openclaw | grep -i 'ready'
# 4. 验证生效
openclaw models
2
3
4
5
6
7
8
9
10
11
12
13
复用规则:改配置后必重启 + 看应用层日志,缺一不可。
# §4 第二类故障:行为级 — "死循环发消息"完整路径
最难诊断的一类故障——进程活着,日志在写,但 Agent 行为完全错乱(来自 <session-file>)。
# 4.1 浏览器 SSRF Policy 拦截
OpenClaw 默认有 browser.ssrfPolicy,阻止 Agent 访问 SSRF 风险 URL(含 localhost、metadata.google.internal、私有 IP 等)。Agent 尝试访问 https://example.com 时被拦截:
browser endpoint blocked by policy
raw_params={"action":"open","url":"https://example.com"}
2
根因:Agent 内部的 Tool 调用链路缺乏"优雅失败"逻辑。
# 4.2 Agent 不优雅退出(核心缺陷)
Agent 的失败处理逻辑应该是:
Tool 调用失败 → 报告错误给用户 → 退出当前 Task → 等用户新指令
但实际表现是:
Tool 调用失败 → 报告错误 → 重试 → 再次失败 → 报告错误 → 重试 ... 死循环
或者更糟:
Tool 调用失败 → 发一条 Telegram 错误消息 → 用户没回应 → 再发 → 再发 ... 消息轰炸
诊断:日志搜索以下关键字:
sudo journalctl -u openclaw-gateway.service | grep -E 'blocked by policy|retry|timeout|tool policy removed'
只要 tool policy removed 在短时间内出现多次(比如 5 分钟内 10+ 次),几乎肯定在死循环。
# 4.3 Tool Policy 频繁重算(雪崩推手)
# 看 Tool Policy 变化频率
sudo journalctl -u openclaw-gateway.service --since "10 minutes ago" | grep -c 'tool policy removed'
# 正常:< 5 次/10 分钟
# 异常:> 20 次/10 分钟 → Agent 在死循环
2
3
4
5
每次 Tool Policy 重算都涉及数据库读写 + 配置解析,11 个 Tool 反复移除/添加会拖垮 Gateway 性能。
# 4.4 修复:3 条措施
# 1. 临时方案:调高 SSRF 白名单
openclaw config patch --stdin <<'JSON5'
{
"browser": {
"ssrfPolicy": {
"allowList": ["example.com", "<internal-domain>.local"]
}
}
}
JSON5
# 2. 强制重启 Gateway(打破任何死循环)
supervisorctl restart openclaw
# 3. 限流 Telegram 推送
openclaw config patch --stdin <<'JSON5'
{
"channels": {
"telegram": {
"rateLimitPerMinute": 5
}
}
}
JSON5
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
根治:升级 Agent 失败处理逻辑(这个需要 OpenClaw 上游修复,但临时措施能止血)。
复用规则:任何 Tool Policy 反复重算都立即重启 Gateway,不要试图让 Agent "自行恢复"。
# §5 第三类故障(最隐蔽):"部分存活"假象
OpenClaw 故障里最难诊断的一类——多个外部通道部分活着,用户以为系统在工作,实际核心已经死了(来自 2026-06-23 换模型死掉)。
# 5.1 Telegram 降级轮询
OpenClaw 的 Telegram 通道在以下情况会"降级":
| 正常模式 | 降级模式 |
|---|---|
| WebSocket 长连接 Gateway | 独立轮询 Telegram API |
| 实时接收消息 | 5-15 秒延迟 |
| Agent 全功能 | 仅基础消息收发 |
降级触发的常见条件:
- Gateway Token Mismatch(CLI 死了)
- Gateway 进程崩溃
- Gateway 过载(CPU/RAM 高)
# 5.2 假象的症状链
[真实状态] CLI: ❌ 死了 Telegram: ⚠️ 降级轮询 Control UI: ⚠️ 慢
[用户感知] "Agent 在 Telegram 还回消息,应该没问题"
[实际] Agent 没有任何真实推理能力,只在机械转发错误
2
3
为什么 Telegram 还能回:
- Telegram Bot Token 在外部 API 上独立鉴权,不依赖 Gateway
- OpenClaw 进程即使崩溃前,Telegram 通道仍在用缓存的 Token poll 新消息
- 但 Agent 主体已经死了,回的内容是缓存的错误模板
# 5.3 假象检测:4 通道逐一 ping
# 1. CLI ping
openclaw infer model providers
# 期望:返回在线 provider 列表
# 异常:报 unauthorized 或 timeout
# 2. Control UI ping
curl -sf http://<IP>:18789/health
# 期望:200 + {"status":"ok"}
# 异常:401/403/timeout
# 3. Telegram 端到端
# 在 Telegram 发 "PING"
# 期望:3 秒内 Agent 回 "PONG"
# 异常:> 30 秒 或 回错误模板
# 4. WebSocket 端到端
wscat -c ws://<IP>:18789/ws
# 期望:连接成功 + 收到 ready 消息
# 异常:连接拒绝 / 立即断开
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
4 个里只要有 1 个异常 = 部分存活,立即排查。
# 5.4 "假死"与"真死"的区分
| 维度 | 假死(部分存活) | 真死(完全停止) |
|---|---|---|
| 进程 | 仍在 | 已退出 |
supervisorctl status | RUNNING | EXITED |
| 应用层日志 | 还在写但内容异常 | 停更 |
| 某个通道 | 部分活 | 全死 |
| Token Mismatch | 很可能 | 通常不是 |
| 重启 | 恢复 | 不一定恢复 |
假死的快速诊断(§3.3 的 Token 一致性检查通常就是答案)。
# §6 OpenClaw 故障定位 10 步法(综合)
把 03 架构、04 配置、08 故障的所有诊断动作合成 10 步法:
[症状] Agent 死了 / 卡了 / 没回应 / 错乱
↓
[1] 拓扑判定:ssh <USER>@<IP> 'which openclaw; systemctl --user status openclaw-gateway'
↓ supervisorctl status openclaw
[2] 服务活着吗?
↓
[3] 进程在吗?ps + ss(端口 18789 在 listen?)
↓
[4] 配置合法吗?openclaw config validate
↓
[5] Provider 在线吗?openclaw infer model providers
↓
[6] Token 一致吗?(sha256 比对 config vs env)
↓
[7] Scope 够吗?openclaw devices list
↓
[8] 端到端 ping:CLI / Control UI / Telegram / WebSocket 4 通道
↓
[9] 看应用层日志:supervisorctl tail -f openclaw | grep ready
↓
[10] 抓包验证:tcpdump vLLM port + grep enable_thinking
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
前 5 步覆盖 80% 故障。步骤 6 解决第二常见的"假死"。步骤 8 暴露"部分存活"。
# §7 故障日志搜索速查
| 关键字 | 含义 | 出处 |
|---|---|---|
gateway token mismatch | Token 双源不一致 | 06-23 |
blocked by policy | SSRF Policy 拦截 / Tool 拒绝 | 06-22 |
tool policy removed | Tool 权限频繁重算(雪崩信号) | 06-22 |
Detected bot identity change | Telegram Token 换生效 | 06-25 |
[gateway] ready | Gateway 重启成功 | 03 / 06 |
unable to open database file | state.db 权限错 | 03 / 04 |
No API key found | Provider 改名未迁移 | 04 |
No journal files were opened | journalctl 权限不足,需 sudo | 06-22 |
discarding stale update offset | Telegram 正常丢弃旧消息 | 06-25 |
# §8 下一篇
下一篇:09|监控告警——7 个真正有用的信号,与"别信进程 RUNNING"的告警设计。
# §9 Agent 可直接解析的元数据块
{
"_meta": {
"doc_version": "2026-06-27",
"article_id": "openclaw-troubleshooting",
"profile_context": "blog",
"estimated_read_time": "14min",
"real_material_count": 2,
"material_sources": [
"notes/claude-code/<session-file>.md",
"notes/claude-code/<session-file>.md"
]
},
"fault_categories": {
"process_level": {
"symptom": "Gateway 进程死了/重启/不响应",
"root_cause": "进程管理 + 配置生效",
"real_case": "换模型死掉(拓扑混淆 + Token Mismatch)"
},
"behavior_level": {
"symptom": "进程活着但 Agent 卡死/死循环/输出错乱",
"root_cause": "应用逻辑(Tool 调用、SSRF、Agent 决策)",
"real_case": "SSRF 死循环发消息"
},
"phantom_level": {
"symptom": "看上去活着但实际不工作",
"root_cause": "多通道部分存活",
"real_case": "Telegram 降级轮询掩盖 CLI 死亡"
}
},
"diagnostic_10_steps": [
"拓扑判定:which openclaw + systemctl/supervisor",
"supervisorctl status openclaw",
"进程存活:ps + ss 端口 18789",
"openclaw config validate",
"openclaw infer model providers",
"Token 一致性:sha256 config vs env",
"openclaw devices list(Scope)",
"4 通道 ping:CLI / Control UI / Telegram / WebSocket",
"应用层日志:grep [gateway] ready",
"tcpdump + grep enable_thinking"
],
"log_search_patterns": {
"gateway_token_mismatch": "config vs env Token 不一致",
"blocked_by_policy": "SSRF Policy 拦截",
"tool_policy_removed": "Tool 权限频繁重算(雪崩信号)",
"detected_bot_identity_change": "Telegram Token 换生效",
"gateway_ready": "Gateway 重启成功",
"unable_to_open_database": "state.db 权限错",
"no_api_key_found": "Provider 改名未迁移"
},
"safety_rules": [
"任何 OpenClaw 操作前先确认拓扑(容器 vs 裸机 vs 源码)",
"远程跑 openclaw 命令前显式 export PATH 和 HOME",
"Token 双源永远让 config 跟随 env",
"改配置后必重启 + 看应用层 ready 日志",
"Tool Policy 反复重算立即重启 Gateway(不依赖 Agent 自恢复)",
"Telegram 还回消息 ≠ Agent 活着,做 4 通道 ping"
],
"verification": {
"token_consistency": "sha256 对比 config + env 的 Token",
"topology_detect": "ssh <USER>@<IP> 'which openclaw; systemctl --user status openclaw-gateway'",
"channel_ping": "CLI + Control UI + Telegram + WebSocket 4 个并行测",
"log_ready_check": "supervisorctl tail -f openclaw | grep ready"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
AI Agent 使用指南:
- 当用户说"Agent 死了" → 先 §5.3 的 4 通道 ping,区分"假死 vs 真死"
- 当用户说"Gateway 不响应" → 走 §3.3 Token Mismatch 排查,sha256 比对
- 当用户说"Telegram 一直在发" → 走 §4 死循环诊断,搜
tool policy removed频率 - 当用户说"ssh 进去找不到 openclaw" → 走 §3.2 显式 export PATH
- 当用户说"两个 OpenClaw 混了" → 走 §3.1 拓扑探测黄金命令