[Bug]: 429 rate limit errors from OpenRouter FREE models not honored?

该问题出现在通过 LiteLLM 调用 OpenRouter 免费模型(ID 以 :free 结尾)或 Gemini/Vertex AI 模型并触发 429 限流时。部分路径下返回体是合法 JSON,但缺少对 HTTP 状态码的检查,导致错误被吞掉,表现为空回复而非抛出 RateLimitError

快速结论:该问题出现在通过 LiteLLM 调用 OpenRouter 免费模型(ID 以 :free 结尾)或 Gemini/Vertex AI 模型并触发 429 限流时。部分路径下返回体是合法 JSON,但缺少对 HTTP 状态码的检查,导致错误被吞掉,表现为空回复而非抛出 RateLimitError。优先排查 LiteLLM 版本和 429 响应处理逻辑。

适用环境:Issue 中已确认的环境为 LiteLLM v1.63.0(原帖)、litellm-proxy v1.63.6-nightly(评论中提及)、Python 3.13(评论堆栈中出现 /usr/lib/python3.13/site-packages)、通过 httpx 发起请求;涉及 OpenRouter 免费模型、Vertex AI Gemini experimental 与 Gemini API 直连。操作系统、CUDA、显卡等 Issue 未提及。

最快修复方案:暂无确认的一步修复方案。Issue 讨论中判断根因是“响应是合法 JSON,缺少对状态码的检查”,属于代码层面问题;可优先尝试升级到包含相关修复的 LiteLLM 版本,或对 429 场景增加重试/降级处理。

注意事项:“缺少状态码检查”是评论者的推断,不是已合入修复的明确结论。免费模型本身有硬性额度(每分钟/每天请求数),即使错误能被正确抛出,超限后仍需等待重置或改用付费模型;本地无法通过配置绕开上游限流。

问题场景

在 LiteLLM 中调用 openrouter/google/gemini-2.0-flash-thinking-exp:free 这类免费模型,循环发送请求。达到 OpenRouter 免费额度(每分钟 20 次、每天 200 次)后,上游返回 429。LiteLLM 的 stream 与 non-stream 两种调用都表现为“正常返回”,但内容为空,未抛出 RateLimitError。评论中另有用户通过 litellm-proxy 调用 Vertex AI Gemini experimental 模型以及 Gemini API 直连时遇到 429,后者在堆栈中能正确抛出 RateLimitError,但 fallback 未按预期切换。

报错原文

{"error":{"message":"Rate limit exceeded: limit_rpd/google/gemini-2.0-flash-thinking-exp-01-21/54276bca-abd7-4aa6-a6b5-1b8f898f1395","code":429,"metadata":{"headers":{"X-RateLimit-Limit":"80","X-RateLimit-Remaining":"0","X-RateLimit-Reset":"1741305600000"}}}}

litellm.RateLimitError: litellm.RateLimitError: VertexAIException - b'{\n  "error": {\n    "code": 429,\n    "message": "Quota exceeded for aiplatform.googleapis.com/generate_content_requests_per_minute_per_project_per_base_model with base model: gemini-experimental. ...",\n    "status": "RESOURCE_EXHAUSTED"\n  }\n}\n'

httpx.HTTPStatusError: Client error '429 Too Many Requests' for url 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro-exp-03-25:streamGenerateContent?...&alt=sse'

原因分析

最可能的原因是:OpenRouter 在 429 时返回的是结构合法、可正常解析的 JSON 错误体,LiteLLM 的 OpenAI 兼容流程可能缺少对该响应 HTTP 状态码的检查,于是把错误体当作正常响应继续处理,最终包装成 finish_reason='stop'、content=None、usage 为 0 的 ModelResponse。评论者明确提出了这一推断。需要注意的是,该推断尚未被确认为根因;在 Gemini 直连场景下 429 能正确抛出 RateLimitError,说明不同 provider 路径的行为并不一致。

环境排查

  • 确认 LiteLLM 版本,原帖报告为 v1.63.0,评论中涉及 v1.63.6-nightly。
  • 确认调用路径:litellm.completion 直调、还是通过 litellm-proxy 转发。
  • 确认是否使用 stream 与 non-stream 两种方式,并对比两者在超限时的表现。
  • 确认 Python 版本(评论堆栈显示 Python 3.13),以及 httpx 相关依赖。
  • 确认所用模型是否为 :free 变体,以及是否已接近 OpenRouter 每分钟/每天额度。

解决步骤

  1. 先用 curl 直接请求 OpenRouter 接口,确认上游确实返回 429 及错误体,排除是 LiteLLM 之外的网络问题。
  2. 在 LiteLLM 中分别测试 stream 和 non-stream 调用,观察超限时是否仍返回空内容的 ModelResponse 而不是抛出 RateLimitError。
  3. 检查与 429 响应状态码处理相关的 LiteLLM 版本更新,可优先尝试升级到较新的版本,验证该问题是否已修复。
  4. 在修复可用前,可在应用层对“内容为空且 usage 为 0”的响应做兜底判断,视为限流并触发重试或 fallback。
  5. 若使用 LiteLLM Proxy 配置 fallback,单独验证 fallback 在 429 时是否生效;评论显示部分场景下 fallback 未按预期触发。

验证方法

在可控条件下把免费模型额度用尽(或通过上游返回 429 的方式复现),确认 LiteLLM 抛出 RateLimitError,而不是返回 content=None 的空响应;配置了 fallback 时,确认请求能切换到备用模型并拿到有效回复。

参考来源

BerriAI/litellm #9035

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 30398

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注