【Bug已解决】openclaw JSON parse error / Unexpected token in JSON — OpenClaw JSON 解析失败解决方案

【Bug已解决】openclaw JSON parse error / Unexpected token in JSON — OpenClaw JSON 解析失败解决方案 【Bug已解决】openclaw: JSON parse error / Unexpected token in JSON — OpenClaw JSON 解析失败解决方案1. 问题描述在使用 OpenClaw 时系统返回 JSON 解析错误无法正常处理响应# JSON 解析失败 - 标准报错 $ openclaw 帮我重构这个函数 Error: JSON parse error Unexpected token in JSON at position 0 # JSON 解析失败 - 响应非 JSON $ openclaw 分析代码 Error: Failed to parse JSON response Expected property name or } in JSON at position 2 # JSON 解析失败 - 截断的 JSON $ openclaw 生成测试用例 Error: Unexpected end of JSON input JSON string is not complete, missing closing brackets # JSON 解析失败 - 类型不匹配 $ openclaw 完成任务 Error: JSON parse error Cannot read property content of undefined这个问题在以下场景中特别常见API 返回了 HTML 错误页面而非 JSON响应被网络中间设备截断网络不稳定导致响应不完整API 版本变更导致响应格式变化中间层服务Nginx/Apache返回错误页企业内网安全网关拦截并替换响应2. 原因分析请求发送 ↓ 到达API端点 ↓ 返回响应 ←──── 可能是HTML错误页 ↓ 尝试JSON.parse() ←──── 失败第一个字符是 不是 { ↓ 抛出 Unexpected token in JSON原因分类具体表现占比API返回HTML错误页响应以html开头约 35%响应被截断JSON不完整约 20%安全网关拦截返回拦截页约 15%API版本变更响应字段缺失约 12%编码问题BOM头干扰约 10%网络不稳定部分数据丢失约 8%深层原理当 OpenClaw 向 API 发送请求时预期收到Content-Type: application/json的响应。但如果请求出错如 502 Bad GatewayAPI 服务器或中间网络设备可能返回一个 HTML 格式的错误页面。OpenClaw 的 JSON 解析器尝试解析这段 HTML 时遇到的第一个字符HTML 标签起始符不是合法的 JSON 起始符因此抛出 Unexpected token 错误。3. 解决方案方案一检查实际响应内容最推荐首先需要看到 API 到底返回了什么而不是仅看到 JSON 解析错误# 使用 curl 直接请求 API 端点查看原始响应 curl -s -o response.txt -w %{http_code} \ https://api.anthropic.com/v1/messages \ -H x-api-key: $ANTHROPIC_API_KEY \ -H content-type: application/json \ -H anthropic-version: 2023-06-01 \ -d {model:claude-sonnet-4-20250514,max_tokens:100,messages:[{role:user,content:hello}]} # 查看响应内容 cat response.txt # 如果看到 HTML 内容说明 API 返回了错误页 head -5 response.txt # 检查 HTTP 状态码 # 200 正常 # 401 API密钥错误 # 429 限流 # 500/502/503 服务端错误如果看到 HTML 错误页需要根据 HTTP 状态码对症处理。方案二检查网络中间设备是否替换响应# 检查实际响应来源 curl -v https://api.anthropic.com/v1/messages 21 | grep -E HTTP|Content-Type|Server # 如果 Server 字段不是 Anthropic 的服务器说明被中间设备拦截 # 典型拦截特征 # - Server: Squid # - Server: Fortinet # - Content-Type: text/html而非 application/json # 检查 DNS 解析是否被劫持 nslookup api.anthropic.com # 对比真实 IP可通过其他 DNS 服务器验证 nslookup api.anthropic.com 8.8.8.8 # 检查系统时间偏差TLS 握手依赖时间同步 date # 如果时间偏差超过 5 分钟可能导致 TLS 握手失败返回错误页 sudo ntpdate ntp.org # 验证连通性 curl -sI https://api.anthropic.com/v1/messages | grep -i content-type # 正常应显示 application/json方案三处理响应截断问题# 创建一个响应完整性检查脚本 import json import sys def validate_json_response(response_text, sourceresponse): 检查 JSON 响应是否完整且合法 if not response_text or not response_text.strip(): print(f[ERROR] {source}: 响应为空) return False stripped response_text.strip() # 检查是否以 HTML 开头 if stripped.startswith() or stripped.startswith(!): print(f[ERROR] {source}: 响应是 HTML 而非 JSON) print(f 前100字符: {stripped[:100]}) return False # 检查是否以 { 或 [ 开头合法 JSON 起始符 if not (stripped.startswith({) or stripped.startswith([)): print(f[ERROR] {source}: 响应不是合法 JSON 格式) print(f 前100字符: {stripped[:100]}) return False # 尝试解析 JSON try: data json.loads(stripped) print(f[OK] {source}: JSON 解析成功) return True except json.JSONDecodeError as e: print(f[ERROR] {source}: JSON 解析失败 - {e}) print(f 错误位置: 行 {e.lineno}, 列 {e.colno}) print(f 错误字符附近: ...{stripped[max(0,e.pos-20):e.pos20]}...) return False # 读取响应文件并验证 if __name__ __main__: if len(sys.argv) 1: with open(sys.argv[1], r) as f: response f.read() validate_json_response(response) else: print(用法: python3 validate_json.py response_file)方案四更新 OpenClaw 和 API 版本# 检查当前 OpenClaw 版本 openclaw --version # 更新到最新版本 pip install --upgrade openclaw # 检查 API 版本配置 cat .openclaw/config.json | grep -i version # 确保 API 版本号正确 # 当前正确的 API 版本为 2023-06-01 # 如果配置了过期的版本号可能导致响应格式变化 # 重置 API 版本配置 python3 -c import json with open(.openclaw/config.json, r) as f: config json.load(f) config[apiVersion] 2023-06-01 with open(.openclaw/config.json, w) as f: json.dump(config, f, indent2) print(API版本已更新为 2023-06-01) 方案五添加响应预处理机制# 在 OpenClaw 配置中添加响应预处理 # 创建 .openclaw/response_handler.py import json import re def preprocess_response(raw_response): 预处理 API 响应处理常见的非 JSON 格式 # 去除 BOM 头 if raw_response.startswith(\ufeff): raw_response raw_response[1:] # 去除前导空白 raw_response raw_response.strip() # 如果响应是 HTML提取错误信息 if raw_response.startswith(): # 尝试从 HTML 中提取 title 或 error 信息 title_match re.search(rtitle(.*?)/title, raw_response, re.IGNORECASE) if title_match: raise ValueError(fAPI 返回 HTML 错误页: {title_match.group(1)}) else: raise ValueError(API 返回 HTML 而非 JSON可能服务端错误) # 如果 JSON 被截断尝试修复 open_braces raw_response.count({) close_braces raw_response.count(}) open_brackets raw_response.count([) close_brackets raw_response.count(]) if open_braces close_braces: raw_response } * (open_braces - close_braces) if open_brackets close_brackets: raw_response ] * (open_brackets - close_brackets) try: return json.loads(raw_response) except json.JSONDecodeError as e: raise ValueError(fJSON 解析失败: {e}\n原始响应前200字符: {raw_response[:200]}) # 测试 if __name__ __main__: test_cases [ {valid: json}, \ufeff{bom: removed}, {truncated: json, htmlbody502 Bad Gateway/body/html, ] for i, test in enumerate(test_cases): print(f\n测试 {i1}: {test[:50]}...) try: result preprocess_response(test) print(f 结果: {result}) except ValueError as e: print(f 错误: {e})方案六重试机制与错误恢复# 配置 OpenClaw 的重试机制 cat .openclaw/retry_config.json EOF { maxRetries: 3, retryDelay: 1000, retryOnParseError: true, fallbackBehavior: raw_output, timeoutMs: 30000 } EOF # 重试包装脚本 cat /usr/local/bin/openclaw-safe SCRIPT #!/bin/bash MAX_RETRIES3 RETRY_DELAY2 for i in $(seq 1 $MAX_RETRIES); do echo [尝试 $i/$MAX_RETRIES] 执行 openclaw... # 捕获输出和错误 OUTPUT$(openclaw $ 21) EXIT_CODE$? # 检查是否有 JSON 解析错误 if echo $OUTPUT | grep -q JSON parse error\|Unexpected token; then echo [警告] 检测到 JSON 解析错误 echo $OUTPUT | tail -5 if [ $i -lt $MAX_RETRIES ]; then echo 等待 ${RETRY_DELAY}s 后重试... sleep $RETRY_DELAY RETRY_DELAY$((RETRY_DELAY * 2)) continue fi fi # 成功或达到最大重试次数 echo $OUTPUT exit $EXIT_CODE done SCRIPT chmod x /usr/local/bin/openclaw-safe echo 安全重试脚本已安装: openclaw-safe4. 各方案对比总结方案适用场景推荐指数方案一检查实际响应所有情况的第一步⭐⭐⭐⭐⭐方案二检查网络设备企业内网环境⭐⭐⭐⭐方案三响应完整性检查截断/不完整响应⭐⭐⭐⭐方案四更新版本API 版本不兼容⭐⭐⭐方案五响应预处理长期防御性方案⭐⭐⭐方案六重试机制偶发性解析失败⭐⭐⭐5. 常见问题 FAQ5.1 Windows 上出现 JSON 解析错误但 Linux 上正常Windows 系统下可能存在编码差异。OpenClaw 在 Windows 上读取配置文件或缓存文件时可能因为 BOMByte Order Mark或 CRLF 换行符导致 JSON 解析失败# Windows PowerShell - 检查文件编码 $bytes [System.IO.File]::ReadAllBytes(.openclaw\config.json) if ($bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { Write-Host 检测到 BOM 头正在移除... $content [System.IO.File]::ReadAllText(.openclaw\config.json) $content $content.TrimStart([char]0xFEFF) [System.IO.File]::WriteAllText(.openclaw\config.json, $content, [System.Text.UTF8Encoding]::new($false)) Write-Host BOM 头已移除 } # 统一使用 UTF-8 无 BOM 编码 # 使用 VS Code 打开配置文件右下角切换编码为 UTF-8无 BOM5.2 Docker 容器中频繁出现 JSON 解析错误Docker 容器中可能因为网络配置问题导致 API 响应被截断# Dockerfile 中确保 DNS 解析正确 RUN echo nameserver 8.8.8.8 /etc/resolv.conf # 或者使用 host 网络模式 # docker run --network host openclaw # 检查容器内是否能正确访问 API docker exec -it container_id curl -sI https://api.anthropic.com/v1/messages # 增大容器 MTU 防止大响应被分片丢失 docker run --mtu1400 openclaw5.3 CI/CD 流水线中出现 JSON 解析错误在 GitHub Actions / GitLab CI 中可能因为网络不稳定或超时配置不当导致响应不完整# .github/workflows/openclaw.yml - name: Run OpenClaw env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} OPENCLAW_TIMEOUT: 60000 OPENCLAW_MAX_RETRIES: 3 run: | # 设置较长的超时时间 export OPENCLAW_REQUEST_TIMEOUT60000 # 使用重试机制 openclaw 任务 || { echo 第一次失败等待重试... sleep 5 openclaw 任务 }5.4 JSON 解析错误只在处理大文件时出现处理大文件时API 响应可能超过缓冲区限制被截断# 检查 OpenClaw 的响应缓冲区设置 openclaw --config | grep -i buffer # 增大响应缓冲区 python3 -c import json with open(.openclaw/config.json, r) as f: config json.load(f) config[responseBufferSize] 10485760 # 10MB config[streamResponse] True # 启用流式响应避免缓冲区溢出 with open(.openclaw/config.json, w) as f: json.dump(config, f, indent2) print(缓冲区已增大至 10MB已启用流式响应) # 启用流式响应模式 openclaw --stream 处理这个大文件5.5 企业内网环境下 JSON 解析错误企业内网的安全策略或 Web 安全网关可能拦截 API 请求并替换为拦截页面# 检查是否有中间设备拦截 curl -v https://api.anthropic.com/v1/messages 21 | grep -E HTTP|Content-Type|Server # 如果 Server 字段不是 Anthropic 的服务器说明被拦截 # 典型拦截特征 # - Server: Squid # - Server: Fortinet # - Content-Type: text/html而非 application/json # 解决方案联系网络管理员将 API 端点加入白名单 # 或使用 OpenClaw 支持的第三方兼容 API 端点 openclaw --api-base https://compatible-api.example.com/v1 任务5.6 更新 OpenClaw 后突然出现 JSON 解析错误新版本可能修改了响应解析逻辑需要检查变更日志# 查看版本变更日志 pip show openclaw | grep -i version openclaw --changelog | head -50 # 回退到上一个稳定版本 pip install openclaw1.2.3 # 替换为之前使用的版本号 # 清除缓存后重试 rm -rf .openclaw/cache/ rm -rf ~/.openclaw/cache/ openclaw 测试任务5.7 同时使用多个 AI 工具时出现 JSON 解析错误多个工具可能共享某些缓存文件或配置导致交叉污染# 检查是否有共享缓存目录 ls -la ~/.cache/ ls -la /tmp/ # 清理可能被污染的缓存 rm -rf /tmp/openclaw_* rm -rf ~/.cache/openclaw/ # 确保 OpenClaw 使用独立的缓存目录 export OPENCLAW_CACHE_DIR$HOME/.openclaw/cache mkdir -p $OPENCLAW_CACHE_DIR openclaw 测试5.8 JSON 解析错误伴随着 502 Bad Gateway502 错误意味着 API 服务端暂时不可用返回的 HTML 错误页被误当作 JSON 解析# 确认是 502 错误 curl -s -o /dev/null -w %{http_code} https://api.anthropic.com/v1/messages # 如果返回 502等待服务恢复后重试 echo API 服务暂时不可用等待恢复... sleep 30 curl -s -o /dev/null -w %{http_code} https://api.anthropic.com/v1/messages # 配置自动检测和等待脚本 while true; do STATUS$(curl -s -o /dev/null -w %{http_code} https://api.anthropic.com/v1/messages) if [ $STATUS 200 ]; then echo API 已恢复 openclaw 任务 break fi echo 当前状态: $STATUS, 等待 30s... sleep 30 done排查清单速查表□ 1. 使用 curl 查看原始 API 响应内容 □ 2. 检查 HTTP 状态码200/401/429/500/502 □ 3. 确认响应 Content-Type 是否为 application/json □ 4. 检查 DNS 解析是否被劫持 □ 5. 检查配置文件是否有 BOM 头Windows □ 6. 清理缓存目录 ~/.openclaw/cache/ □ 7. 确认 OpenClaw 版本和 API 版本兼容 □ 8. 检查响应是否被截断大文件场景 □ 9. 验证网络环境是否有安全策略拦截 □ 10. 尝试启用流式响应模式6. 总结最常见原因API 返回 HTML 错误页如 502JSON 解析器遇到字符报错占 35%首要排查用curl直接请求 API 查看原始响应区分是服务端问题还是本地解析问题网络排查企业网络中的安全网关/安全策略可能替换 API 响应为拦截页面防御措施启用流式响应、增大缓冲区、添加重试机制最佳实践建议在生产环境中配置响应预处理脚本自动识别 HTML 错误页并提取有用信息而非直接抛出 JSON 解析错误故障排查流程图flowchart TD A[JSON解析错误] -- B[查看原始响应] B -- C[curl请求API] C -- D{响应是HTML?} D --|是| E[检查HTTP状态码] D --|否| F[检查JSON完整性] E -- G{状态码} G --|401| H[修复API密钥] G --|429| I[等待限流恢复] G --|500/502| J[等待服务恢复] G --|200| K[检查网络设备拦截] H -- L[openclaw测试] I -- L J -- M[sleep 30s重试] M -- L K -- N[联系网络管理员] N -- L F -- O{JSON截断?} O --|是| P[增大缓冲区] O --|否| Q[检查BOM/编码] P -- R[启用流式响应] R -- L Q -- S[移除BOM头] S -- L L -- T{成功?} T --|是| U[✅ 问题解决] T --|否| V[更新OpenClaw版本] V -- W[清理缓存重试] W -- X{成功?} X --|是| U X --|否| Y[配置重试机制] Y -- Z[使用openclaw-safe] Z -- U