[Bug]: Redacted tool-call arguments (“redacted-by-litellm”) spam “Failed to parse tool call arguments” warnings via spend-log tool index

这个问题在 LiteLLM 1.94.x/1.95.x 版本中,开启 turn_off_message_logging: true 且启用数据库 spend logs 时触发。升级后引入的 _redact_tool_calls 会把工具参数替换成 redacted-by-litellm 占位符,而

快速结论:这个问题在 LiteLLM 1.94.x/1.95.x 版本中,开启 turn_off_message_logging: true 且启用数据库 spend logs 时触发。升级后引入的 _redact_tool_calls 会把工具参数替换成 redacted-by-litellm 占位符,而 spend-log 路径随后试图用 json.loads 解析这个自我写入的占位符,导致刷屏警告。优先排查方向是确认是否可升级到包含修复 PR(#36658)的版本,或临时回退到 1.93.x。

适用环境:LiteLLM v1.94.x 至 v1.95.x(报告出现于 v1.95.0,评论中提到从 1.92.2 或 1.93 升级到 1.94.3/1.95 后出现);使用数据库 spend logs 的代理环境;面向 Claude Code、opencode 等 agentic 客户端的部署场景。

最快修复方案:暂无确认的一步修复方案。Issue 提到有 PR(#36658)通过跳过对已编辑参数的解析来解决,但在该 PR 合并前,最干净的办法是固定 LiteLLM 版本到 1.93.x(即升级前未引入 _redact_tool_calls 的版本)。如果必须保持当前版本,可以过滤来自 factory.py:5380 的 WARNING 级日志。

注意事项:回退版本可能涉及其他功能变更,需评估兼容性;过滤日志只是掩盖问题而非修复;general_settings.disable_spend_logs 虽然能静默其中一个调用点,但会同时禁用 spend 日志,对需要计费网关的用户不可接受。

问题场景

LiteLLM 代理在 litellm_settings.turn_off_message_logging: true 且启用数据库 spend logs 时,每个包含工具调用的流式响应都会在每个工具调用后输出一条 WARNING 日志。面向 Claude Code、opencode 等编码代理时,几乎所有响应都带工具调用,导致该警告反复刷屏——实测在约 12 分钟内,1773 个 /v1/messages 请求产生 958 条警告,按 2.6 req/s 推算每天约产生 12 万行此类警告。

报错原文

{"message": "Failed to parse tool call arguments: Failed to parse tool call arguments for tool 'Read' (chat completions). Error: Expecting value: line 1 column 1 (char 0). Arguments: redacted-by-litellm", "level": "WARNING", "component": "LiteLLM", "logger": "factory.py:5380"}

原因分析

问题根源在于 LiteLLM 1.94.x 引入的 _redact_tool_calls(位于 redact_messages.py)。该函数在消息日志关闭时,会把工具调用的 arguments 替换为 redacted-by-litellm 占位符。随后 spend-log 路径上的 response_tool_call_names 会尝试对每个调用执行 json.loads 解析参数。解析占位符字符串必然失败(无任何括号或花括号),从而产生 WARNING。

关键因素:

  • v1.94.x 重写了 spend-log 模块,将响应工具调用的处理统一路由到共享的 get_tool_calls_from_response,该辅助函数会为所有调用者(包括只需名称的调用者)急切解析 arguments
  • 同一请求有两个独立调用点(db_spend_update_writer.py:185_enqueue_tool_usage_transactiondb_spend_update_writer.py:340_enqueue_tool_registry_upsert)都执行 response_tool_call_names,因此每个工具调用会解析两次、警告两次。
  • _attempt_json_repair 无法修复占位符——输入没有任何未匹配的开括号/花括号时会返回 None,因此全部走 raise 路径。

此问题不影响 Anthropic Messages 分支(tool_use 块的 input 是已解析的字典,直接跳过解析器),但 /v1/messages 仍会命中 chat 分支,因为透传日志处理器在回调运行前把 SSE 流重建成了 chat-completions 的 ModelResponse

功能上并没有实际损坏:_parse_tool_call_arguments 会吞掉 ValueError 并返回 {},唯一消费方只读取 redaction 未触碰的 tool_call["name"],因此工具使用跟踪、LiteLLM_SpendLogToolIndexLiteLLM_DailyToolSpend 都保持正确。问题纯粹在于一个正常的、预期的、自我引发的条件在热路径上以 WARNING 级别被报告。

环境排查

  • 确认 LiteLLM 版本是否在 v1.94.x 至 v1.95.x 范围(v1.93.x 及更早版本无 _redact_tool_calls,不触发此问题)。
  • 确认 litellm_settings.turn_off_message_logging 是否为 true
  • 确认是否启用了数据库 spend logs(DB spend logs)。
  • 检查部署是否使用代理模式(database-backed proxy)。
  • 客户端是否为 Claude Code、opencode 等频繁产生工具调用的 agentic 工具。

解决步骤

  1. 优先尝试:关注并等待 PR #36658 合并。该 PR 通过跳过对已编辑(redacted)参数的解析来解决问题。合并后升级到包含该修复的版本即可。
  2. 在修复版本可用前,最干净的规避方案是将 LiteLLM 固定回 v1.93.x(或升级前未引入 _redact_tool_calls 的版本)。
  3. 如果必须保持当前版本,可过滤来自 factory.py:5380 的 WARNING 级日志。注意:LITELLM_LOG 环境变量只作用于导入时创建的 handler,且 json_logs: true 会重置所有 logger 的 handler 并丢弃该配置;目前没有代码路径会把 verbose_logger 提升到 WARNING 以上。
  4. 不要使用 general_settings.disable_spend_logs 来压制此问题——它只静默两个调用点之一并禁用整个 spend 日志功能,对需要计费网关的场景不可接受。

验证方法

升级或回退版本后,在 turn_off_message_logging: true 和 DB spend logs 开启的情况下,发送包含工具调用的流式请求,观察日志中不再出现 Failed to parse tool call arguments 且包含 redacted-by-litellm 的 WARNING。同时确认工具使用跟踪(tool-usage tracking)和 spend 日志统计仍正常写入数据库。

参考来源

BerriAI/litellm #36647

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 20279

发表回复

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