Claude Code fetch 失败完整排查指南:网络、权限、环境配置逐项诊断

在 Claude Code 的工程化实践中,“fetch 失败”几乎是最常见的网络类报错。从最简单的网络不可达,到 TLS 证书、代理配置、权限与运行环境,每个环节都可能导致 fetch 无响应或返回非 200。本文提供一套完整的排查清单与诊断脚本,帮助你从现象快速定位根因并恢复。

典型症状与快速定位

常见错误信息(及其可能根因)

  • ECONNREFUSED:目标端口不可达 / 防火墙阻断
  • ENOTFOUND:DNS 解析失败
  • CERT_HAS_EXPIRED / UNABLE_TO_VERIFY_LEAF_SIGNATURE:证书过期或链不完整
  • ETIMEDOUT:连接超时(网络、代理、防火墙)
  • 401 / 403:认证失败(API Key、权限)
  • 429:速率限制
  • 502 / 503:上游服务异常

快速决策树

  1. 本机 curl 同一 URL 能否成功?→ 能则环境/权限问题,不能则网络/证书问题
  2. 仅该域名失败,其他域名正常?→ DNS 或证书问题
  3. 所有 HTTPS 都失败?→ CA 根证书/Node.js 版本问题
  4. 内网/代理环境?→ 代理配置/白名单问题

第一步:基础连通性验证

在 Claude Code 环境内外分别进行验证,判断是代码问题还是环境问题。

1.1 在 Claude Code 内执行 fetch 测试

// 在 Claude Code 终端或 REPL 中运行
const testFetch = async (url) => {
  try {
    const res = await fetch(url);
    console.log('Status:', res.status);
    const text = await res.text();
    console.log('Length:', text.length);
    return res.status;
  } catch (e) {
    console.error('Error:', e.cause?.code || e.message);
    throw e;
  }
};

await testFetch('https://www.google.com'); // 参考公网
await testFetch('https://api.anthropic.com'); // 目标 API

1.2 在宿主机用 curl 复现

# 简单连通性
curl -I https://api.anthropic.com

# 带详细错误与时间
curl -v --trace-ascii - https://api.anthropic.com > /tmp/curl-trace.log

# 若使用代理
curl -x http://proxy.example.com:8080 -I https://api.anthropic.com

判定

  • 内外都失败 → 网络层问题(防火墙、路由、代理)
  • 仅 Claude Code 内失败 → 环境/权限/运行时问题

第二步:网络与 DNS 诊断

2.1 DNS 解析检查

# 解析目标域名
nslookup api.anthropic.com
dig api.anthropic.com +short

# 检查 hosts 文件是否覆盖
cat /etc/hosts | grep api.anthropic.com

2.2 防火墙与端口检查

# 尝试 Telnet 目标端口
nc -zv api.anthropic.com 443

# 检查本机出站规则(Linux)
sudo iptables -L OUTPUT -v -n | grep -E 'REJECT|DROP'

2.3 代理配置检查

# 环境变量
env | grep -i proxy

# Node 的 HTTP_PROXY/HTTPS_PROXY/NO_PROXY
echo $HTTP_PROXY $HTTPS_PROXY $NO_PROXY

# .npmrc 配置(影响 npm 请求)
cat ~/.npmrc | grep -i proxy

第三步:TLS/证书问题排查

3.1 检查证书有效期与链

# 查看证书详细信息
openssl s_client -showcerts -connect api.anthropic.com:443 </dev/null 2>/dev/null | openssl x509 -noout -dates

# 验证证书链
openssl s_client -connect api.anthropic.com:443 -showcerts </dev/null

3.2 更新 Node.js 根证书(过时版本常见)

# 更新至最新的内置 CA 列表
npm update npm -g
# 或在代码中指定 CA(谨慎,仅用于内网/自签名)
process.env.NODE_EXTRA_CA_CERTS = '/path/to/ca-bundle.crt';

3.3 内网自签名证书(开发环境)

// 仅用于开发,生产环境应使用正规证书
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // 关闭验证

第四步:认证与权限排查

4.1 验证 API Key 有效性与作用域

# 使用官方 API 测试(以 Anthropic 为例)
curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-3-5-sonnet-20241022","max_tokens":1,"messages":[{"role":"user","content":""}]}'

4.2 检查速率限制与配额

  • 查看云服务商控制台的配额与用量
  • 429 响应头中通常包含 retry-after

4.3 权限最小化与 CORS

  • 确认调用来源 IP 是否在白名单
  • 浏览器端调用需关注 CORS;服务端调用无此限制

第五步:Claude Code 运行环境特定问题

5.1 工作目录与 .env 文件

  • 确认 .env 加载顺序与变量覆盖
  • 优先级:代码显式 > .env > 系统环境变量

5.2 Node 版本与依赖

node -v
npm ls node-fetch
  • 推荐使用 Node 18+(内置 fetch)
  • 若用旧版本,确保安装 node-fetch 且 import 方式正确

5.3 沙箱/容器环境

  • 检查是否有 seccomp/AppArmor/SELinux 策略限制
  • 容器内需注意 DNS 配置(/etc/resolv.conf)

一键诊断脚本

将以下脚本保存为 fetch-diag.sh,在 Claude Code 环境目录中执行:

#!/usr/bin/env bash
set -euo pipefail

TARGET_URL="${1:-https://api.anthropic.com}"
echo "🔍 诊断目标: $TARGET_URL"

echo ""
echo "=== 1. DNS 解析 ==="
dig +short "$(echo "$TARGET_URL" | sed -E 's|https?://||' | cut -d/ -f1)" || true

echo ""
echo "=== 2. 连通性(nc)==="
HOST="$(echo "$TARGET_URL" | sed -E 's|https?://||' | cut -d/ -f1)"
PORT=443
nc -zv -w 5 "$HOST" "$PORT" || true

echo ""
echo "=== 3. TLS 证书有效期 ==="
echo | openssl s_client -showcerts -servername "$HOST" -connect "$HOST:443" 2>/dev/null | openssl x509 -noout -dates || true

echo ""
echo "=== 4. HTTP 状态码(curl)==="
HTTP_CODE=$(curl -o /dev/null -s -w "%{http_code}\n" --max-time 10 "$TARGET_URL" || echo "000")
echo "HTTP $HTTP_CODE"

echo ""
echo "=== 5. 环境代理 ==="
env | grep -i proxy || echo "未设置 HTTP_PROXY/HTTPS_PROXY"

echo ""
echo "=== 6. Node 版本 ==="
node -v || echo "Node 不在 PATH"

echo ""
echo "=== 7. npm fetch 依赖 ==="
npm ls node-fetch 2>/dev/null || echo "未安装 node-fetch"

echo ""
echo "✅ 诊断完成。"

使用示例:

bash fetch-diag.sh https://api.anthropic.com

常见根因与速查表

现象可能原因一键验证
全部 HTTPS 失败Node 根证书过期更新 Node 或设置 NODE_EXTRA_CA_CERTS
仅某域名失败DNS/证书/封禁openssl s_client + dig
curl 成功、代码失败代理/环境变量/权限对比 env 与代码变量
持续 429触发速率限制减小请求频率或增加重试退避
401/403API Key/权限/白名单用 curl 复现并验证凭证
ENOTFOUNDDNS 污染/劫持/错误切换 DNS(1.1.1.1 / 8.8.8.8)

最佳实践:可复用的错误处理

在 Claude Code 项目中封装统一的 fetch 封装层,自动重试与日志:

interface FetchOptions extends RequestInit {
  retry?: number;
  timeout?: number;
}

async function robustFetch(url: string, options: FetchOptions = {}): Promise<Response> {
  const { retry = 3, timeout = 30000, ...fetchOptions } = options;
  let lastError: Error;

  for (let i = 0; i < retry; i++) {
    try {
      const controller = new AbortController();
      const id = setTimeout(() => controller.abort(), timeout);
      const res = await fetch(url, { ...fetchOptions, signal: controller.signal });
      clearTimeout(id);
      if (!res.ok) {
        const text = await res.text().catch(() => '');
        throw new Error(`HTTP ${res.status}: ${text.slice(0, 200)}`);
      }
      return res;
    } catch (e) {
      lastError = e as Error;
      console.warn(`[Retry ${i + 1}/${retry}]`, e);
      await new Promise(r => setTimeout(r, 1000 * (i + 1))); // 指数退避
    }
  }
  throw lastError;
}

// 使用示例
await robustFetch('https://api.anthropic.com/v1/messages', {
  method: 'POST',
  headers: { 'x-api-key': process.env.ANTHROPIC_API_KEY!, 'content-type': 'application/json' },
  body: JSON.stringify(payload),
  retry: 3,
  timeout: 15000,
});

小结

“fetch 失败”的排查核心在于分层验证:先在宿主机复现,再对比 Claude Code 内环境;从 DNS/连通性到 TLS/代理再到认证/权限,逐项排除。本文提供的一键诊断脚本与统一封装层,可大幅提升工程化场景的定位与恢复效率。

如遇复杂网络拓扑(企业内网、多地代理、堡垒机),建议使用 tcpdump/wireshark 抓包确认握手细节,或与网络团队协同检查白名单与路由规则。