VPSKnow

OpenAI / Claude / Gemini API 超时、401、403、429、5xx 怎么排查?

初级-中级
33分钟

AI API 排障最怕把所有问题都叫“网络不行”。其实超时、401、403、429 和 5xx 是不同层的问题:有的该查终端出口,有的该换 Key,有的该降并发,有的只需要等服务恢复。先分层,后动手,能少走很多弯路。

本文只讨论本人账号、正常项目和合规 API 调用。不要把完整 API Key、Cookie、代理订阅、用户隐私数据或完整请求日志发给别人排查;不要使用来路不明的 API 中转、共享账号或关闭 TLS 校验来处理正式项目问题。

🎯 这篇适合谁

  • 你在 Codex、Cursor、Node.js、Python、Docker 或 VPS 上调用 OpenAI / Claude / Gemini API。
  • 浏览器能打开 AI 工具,但代码里一直超时、401、403、429 或 5xx。
  • 你需要把开发环境、远程 VPS、CI/CD 和生产环境的 API 故障排查流程统一起来。
  • 你不想每次出错都盲目换节点、换 Key、换模型,而是希望快速判断到底是哪一层坏了。

🧭 第一原则:先分清是哪一层坏了

排查顺序建议固定成一条线:执行位置 → 出口 IP → DNS/TLS → 代理变量 → API Key → 项目和模型权限 → 额度和限流 → 服务端状态。

如果请求根本连不上服务端,先查网络。只要服务端已经返回了 401、403、429 或 5xx,就说明 TCP、DNS 和 TLS 至少已经走到 API 入口了,这时继续乱换代理通常效率很低。

OpenAI

401 / 403 / 404 / 429 / 5xx

重点看 Authorization、项目、模型权限、速率限制和服务端错误。

Claude API

400 / 401 / 403 / 404 / 413 / 429 / 5xx

Anthropic 文档对请求体大小、认证、权限、限流和 overloaded 有明确分类。

Gemini API

400 / 401 / 403 / 404 / 429 / 500 / 503

Google 文档建议按 API key、权限、配额、模型名和服务可用性排查。

🧾 常见错误快速判断表

现象 优先判断 下一步
连接超时 / timeout 网络层 先查终端出口、DNS、IPv6、代理变量、远程 VPS 出口,不要先换 API Key。
DNS 解析失败 DNS 层 确认执行命令的位置,本地、WSL、Remote SSH、Docker 容器可能使用不同 DNS。
TLS / certificate 错误 证书层 检查系统时间、公司代理、安全软件、证书链;不要关闭 TLS 校验凑合上线。
401 Unauthorized 认证层 Key 不存在、写错、过期、环境变量没读到,或请求 Header 写错。
403 Forbidden 权限层 Key 可识别,但项目、组织、地区、模型、账单或策略权限不允许。
404 Not Found 资源层 接口路径、模型名、文件 ID、项目资源 ID 写错,或资源不属于当前项目。
429 Rate limit 限流/额度 请求太密、并发太高、额度不足或触发速率限制;要降并发、排队、退避重试。
500 / 502 / 503 / 504 服务端/网关 短时间重试、指数退避、记录 request id,持续异常再查官方状态页。

🧪 先做最小连通性测试

先用最小请求判断“能不能连到 API 入口”。不要一上来跑完整业务代码,因为业务代码里可能同时混有代理、SDK、模型名、数据库、队列和日志系统的问题。

  # 1. 不带 Key:只确认域名、DNS、TLS 和 HTTP 能否走到服务端
curl -i https://api.openai.com/v1/models
curl -i https://api.anthropic.com/v1/models
curl -i https://generativelanguage.googleapis.com/v1beta/models

# 2. 带 Key:只在自己的终端执行,不要截图完整 Header
curl -i https://api.openai.com/v1/models \
  -H "Authorization: Bearer $OPENAI_API_KEY"

curl -i https://api.anthropic.com/v1/models \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01"

curl -i "https://generativelanguage.googleapis.com/v1beta/models?key=$GEMINI_API_KEY"

第一组不带 Key 的请求即使返回 401 或 404,也比超时更有价值:它说明域名、DNS、TLS 和 HTTP 至少通了。第二组带 Key 的请求用于判断认证和权限,执行时不要截图完整 Header。

🌐 网络层:超时、DNS、TLS、IPv6

超时、DNS 失败、TLS 握手失败通常不是 API Key 问题。先确认命令到底在哪里执行:本地 PowerShell、WSL、Cursor 终端、Remote SSH、Docker 容器和 CI/CD runner 都可能是不同出口。

  # 看命令到底在哪台机器执行
hostname
pwd

# 看出口 IP,Remote SSH / Docker / WSL 要分别执行
curl -4 ipinfo.io
curl -6 ipinfo.io

# DNS 解析
nslookup api.openai.com
nslookup api.anthropic.com
nslookup generativelanguage.googleapis.com

# 强制 IPv4 / IPv6 观察差异
curl -4 -I https://api.openai.com/v1/models
curl -6 -I https://api.openai.com/v1/models

# 观察 TLS 和连接阶段
curl -vI https://api.openai.com/v1/models

如果 `curl -4` 能通、`curl -6` 不通,说明 IPv6 可能在拖后腿;如果本地通、Remote SSH 不通,问题在远程 VPS 出口;如果宿主机通、容器不通,就要单独配置 Docker 网络或容器代理。

  # Linux / macOS / VPS / WSL
env | grep -i proxy

# Windows PowerShell
Get-ChildItem Env: | Where-Object { $_.Name -match 'proxy' }

# 临时代理示例,只对当前终端窗口生效
export HTTPS_PROXY=http://127.0.0.1:7890
export ALL_PROXY=socks5://127.0.0.1:7890

代理变量只影响当前终端或对应进程。浏览器代理、系统代理、Cursor UI、VS Code Remote、Docker daemon 并不会天然共享同一套设置。

🔐 认证层:401、Key、环境变量

401 通常表示服务端没有识别到有效认证。最常见原因是环境变量没读到、Key 写错、Header 名称不对、复制时多了空格、Key 已被轮换或删除。

  # 检查变量是否存在,不要把完整 Key 打出来
test -n "$OPENAI_API_KEY" && echo "OPENAI_API_KEY is set"
test -n "$ANTHROPIC_API_KEY" && echo "ANTHROPIC_API_KEY is set"
test -n "$GEMINI_API_KEY" && echo "GEMINI_API_KEY is set"

# Windows PowerShell
if ($env:OPENAI_API_KEY) { "OPENAI_API_KEY is set" }
if ($env:ANTHROPIC_API_KEY) { "ANTHROPIC_API_KEY is set" }
if ($env:GEMINI_API_KEY) { "GEMINI_API_KEY is set" }

排查 401 时,不要把完整 Key 打出来。只确认变量存在,必要时用后台重新生成一个最小权限 Key,再替换本地、VPS、CI/CD 和部署平台里的旧值。

🧩 权限层:403、404、模型和项目权限

403 和 404 不一定是网络问题。Key 被识别了,但当前项目、组织、账单、地区、模型权限或资源 ID 不匹配,也会报这类错误。

  • 确认模型名是否写错,是否仍然可用,是否属于当前项目可以调用的范围。
  • 确认文件、向量库、线程、项目等资源 ID 是否来自同一个账号或项目。
  • 确认 SDK 的 base URL、API 版本、请求路径是否和供应商文档一致。
  • 确认生产环境读取的是生产 Key,不是本地练手 Key 或已经删除的旧 Key。

⏱️ 额度与限流:429 怎么处理

429 可能是短时间请求太密、并发太高、额度不足、免费额度到期,或项目级限制太低。正确做法是降并发、加队列、缓存结果、做有限次数指数退避,而不是在循环里疯狂重试。

  async function requestWithRetry(fn, maxAttempts = 4) {
  for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
    try {
      return await fn();
    } catch (error) {
      const status = error.status || error.response?.status;
      const retryable = status === 429 || status >= 500;

      if (!retryable || attempt === maxAttempts) {
        throw error;
      }

      const delayMs = Math.min(1000 * 2 ** (attempt - 1), 8000);
      await new Promise((resolve) => setTimeout(resolve, delayMs));
    }
  }
}

对用户可见的产品,建议把 429 设计成可恢复状态:提示稍后重试、进入队列、保存草稿或降级到轻量模型。不要让前端一直无提示等待。

🛠️ 服务端错误:5xx 与重试策略

500、502、503、504 多数属于服务端、网关、上游过载或临时不可用。可以有限重试,但要设置最大次数和超时。持续异常时记录 request id、时间、模型、地区、供应商和环境,再查官方状态页或工单。

  • 不要对 401 / 403 无限重试,这只会浪费额度和日志空间。
  • 不要把所有 5xx 都归因于供应商,也要排查自己代理、中转、网关、队列和函数超时。
  • 生产项目要给 API 调用设置超时、重试、熔断和降级文案。

📝 日志怎么留才安全

好的日志能定位问题,坏的日志会泄露密钥。记录状态码、错误类型、request id、模型、运行环境和尝试次数就够了,不要记录完整 Key、Cookie、代理账号密码或用户隐私数据。

  // 推荐记录这些
{
  "provider": "openai",
  "status": 429,
  "error_type": "rate_limit",
  "request_id": "req_xxx",
  "model": "gpt-...",
  "runtime": "vps-prod",
  "region": "us-west",
  "attempt": 2
}

// 不要记录这些
{
  "authorization": "Bearer sk-...",
  "api_key": "...",
  "full_prompt": "含用户隐私或业务数据的完整提示词",
  "cookie": "...",
  "proxy_url": "含账号密码的代理地址"
}

如果日志已经泄露了 Key,按泄露处理:先吊销或轮换,再清理代码、日志、CI/CD、部署平台和 Git 历史。

排查清单

执行位置

本机、WSL、Remote SSH、Docker、CI/CD、VPS 生产机分别确认,不要混在一起。

出口 IP

终端出口是否和你预期的 AI 节点、VPS 落地或海外开发机一致。

DNS / TLS

DNS 是否解析,TLS 是否握手,系统时间是否正确,IPv6 是否拖后腿。

Key 与 Header

环境变量是否读到,Header 名称是否符合对应服务,Key 是否已经轮换或禁用。

接口和模型

URL 路径、API 版本、模型名、项目资源 ID 是否正确。

账单和额度

是否欠费、额度用尽、免费额度到期、项目限额太低或并发太高。

重试策略

只对 429 和 5xx 做有限次数退避重试,不要对 401 / 403 无限重试。

日志脱敏

记录状态码、错误类型、request id、环境和时间,不记录 Key、Cookie、完整用户数据。

🧭 站内推荐路径

📚 资料来源

🚀 下一步行动