[Bug]: Global max_budget_limiter instantiated but never registered (Budget Bypass)

用户在运行 LiteLLM Proxy 时,为全局或特定用户设置了较低的 max_budget (例如 max_budget: 0.0001 ),但发送超出预算的多个请求后,Proxy 仍然继续处理请求并产生费用,没有触发 BudgetExceededError 并返回 429 状态码。

快速结论:此报错通常出现在 LiteLLM Proxy 中,当设置了 max_budget 但预算限制被完全绕过时触发。优先排查 _PROXY_MaxBudgetLimiter 是否通过 add_litellm_callback 正确注册为回调。

问题场景

用户在运行 LiteLLM Proxy 时,为全局或特定用户设置了较低的 max_budget(例如 max_budget: 0.0001),但发送超出预算的多个请求后,Proxy 仍然继续处理请求并产生费用,没有触发 BudgetExceededError 并返回 429 状态码。

报错原文

# The limiter is instantiated here:
self.max_budget_limiter = _PROXY_MaxBudgetLimiter()

# However, a grep for the instance variable shows it is NEVER registered:
grep -n "max_budget_limiter\." litellm/utils.py

原因分析

可能原因:litellm/utils.py 中,_PROXY_MaxBudgetLimiter 被实例化为 self.max_budget_limiter,但该实例变量并未通过 litellm.logging_callback_manager.add_litellm_callback() 注册为回调。这意味着 async_pre_call_hook(应阻止超出预算的请求)永远不会被触发,导致预算强制功能被完全绕过。

然而,后续调查表明,在当前的 staging 版本中,真正的注册通过 litellm/proxy/hooks/__init__.py 中的工厂函数 PROXY_HOOKS 完成,并且在 Proxy 启动时由 startup_event() 调用 ProxyLogging._add_proxy_hooks() 来实例化并注册所有钩子。因此,如果特定版本中预算强制仍然失效,根本原因可能在其他地方(例如 max_budget_limiter.py 中的 async_pre_call_hook 跳过了团队关联的密钥,这在 Issue #27394 中单独跟踪)。

此外,Issue 还指出,预算强制作为分散的回调实现,缺乏显式的授权步骤,导致测试无法覆盖,且绕过问题会静默失败。

环境排查

  • LiteLLM 版本(报错提及 v1.83.10,请确认当前版本是否是最新或包含修复)
  • 检查 Proxy 配置文件中的 max_budget 设置是否正确应用
  • 确认 Proxy 启动日志中是否有 _PROXY_MaxBudgetLimiter 注册成功的记录
  • 验证是否使用了团队关联的密钥(可能导致预算钩子被跳过)

解决步骤

  1. 确认实例化与注册:检查 litellm/utils.pyself.max_budget_limiter = _PROXY_MaxBudgetLimiter() 的实例化行(约第 352 行)。可优先尝试:立即在该行之后添加注册代码:litellm.logging_callback_manager.add_litellm_callback(self.max_budget_limiter)
  2. 检查工厂注册:查看 litellm/proxy/hooks/__init__.py 中的 PROXY_HOOKS 字典,确认 "max_budget_limiter": _PROXY_MaxBudgetLimiter 条目是否存在。
  3. 确认 Proxy 启动时调用:在 litellm/utils.py 中找到 ProxyLogging._add_proxy_hooks() 方法(约第 484-501 行),验证它会迭代 PROXY_HOOKS,实例化每个钩子类,并通过 add_litellm_callback() 注册。
  4. 追踪 async_pre_call_hook:如果预算强制仍然失效,检查 max_budget_limiter.py 中的 async_pre_call_hook 实现,尤其是是否在 32-33 行跳过了团队关联密钥。
  5. 考虑设计级修复:Issue 建议实现显式的预算授权步骤(如原子预留机制 reserve → commit → refund),以替代分散的回调实现。这需要更改架构而非简单补丁。

验证方法

应用修复后,重新启动 LiteLLM Proxy 并执行以下验证:

  • 在配置文件中设置一个极低的 max_budget(如 0.0001)。
  • 发送超出此预算的多个请求。
  • 确认 Proxy 返回 429 状态码,且日志中显示 BudgetExceededError
  • 检查回调注册日志,确认 _PROXY_MaxBudgetLimiter 已成功注册。

参考来源

BerriAI/litellm #27381

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 16195

发表回复

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