快速结论:当 Open WebUI 在原生工具调用流程里连续触发多次 tool call(尤其是“先并行搜索、再基于结果追加一次搜索”)时,convert_output_to_messages() 会把后一次的 tool call 合并进上一条 assistant 消息,导致该 call 与其 reasoning_details 分离、对话顺序错乱,最终向 Gemini 发起的下一次请求被上游以 HTTP 400 拒绝。优先排查后端消息转换逻辑,而不是模型或网络本身。
适用环境:Issue 已确认的环境为 Open WebUI v0.11.4、Docker(镜像 ghcr.io/open-webui/open-webui:latest-slim)、操作系统 Debian 12;上游为 openai-compatible 网关 https://ai-gateway.vercel.sh/v1,模型 google/gemini-3.8-flash。Issue 未提供 Ollama、Python、CUDA 或显卡版本的确认信息。
最快修复方案:暂无确认的一步修复方案。Issue 中提出并在本地回放中验证有效的方向是:在 backend/open_webui/utils/misc.py 收集新的有效 call 之前,先 flush 上一步的 tool 输出,即在 function_call 分支里调用 flush_tool_outputs() 和 flush_tool_images();评论中维护者标注该问题已在 dev 分支修复(test dev / fixed in dev),未说明具体版本号。
注意事项:上述补丁作者的验证属于精简的、非流式的回放(minimal search_web 声明,并非完整 WebUI 请求抓取),只能证明“续接恢复、模型会继续请求工具调用”,尚未完成从浏览器完整跑到最终回答的端到端验证。不要把回放中的 HTTP 200 直接等同于线上问题已完全消除。另外该 issue 被标记为可能与 #31588 重复。
问题场景
用户在 Open WebUI 中运行原生工具调用(native tool calling)工作流,模型为 Gemini 系列(google/gemini-3.8-flash),触发条件是模型先发起并行的多个 web search,再在读取这些结果后追加第三次搜索。工具本身全部执行成功,但随后的下一步模型请求失败,报 HTTP 400。
触发提示词原文为:
Tell me about Claude Opus 5.5 and compare it with GPT 6 Astra.
该问题在最新 release 和提交时的 dev 分支上均可复现。
报错原文
Upstream openai-compatible request failed: HTTP 400 (upstream_error)
url=https://ai-gateway.vercel.sh/v1 model=google/gemini-3.8-flash
code=AI_APICallError message=Request contains an invalid argument.
本地可复现的最小断言失败如下(同一 issue 提供的 snippet):
from open_webui.utils.misc import convert_output_to_messages
def call(id):
return {"type": "function_call", "call_id": id, "name": "search_web",
"arguments": '{}', "status": "completed"}
def result(id):
return {"type": "function_call_output", "call_id": id,
"output": [{"type": "input_text", "text": "result " + id}]}
messages = convert_output_to_messages(
[call("A"), result("A"), call("B"), result("B")], raw=True
)
print(messages)
assert [c["id"] for c in messages[0]["tool_calls"]] == ["A"]
# AssertionError: 第一条 assistant 消息中同时包含 A 和 B
原因分析
核心原因是 convert_output_to_messages() 在重建消息历史时的边界处理有误:当上一步的 tool result 仍处于缓冲状态时,后续出现的 function_call 会被合并进上一条 assistant 消息,而不是开启一条新的 assistant 消息。
这带来两个后果:
- 后一个 call(示例中的 C)被搬到错误的 assistant 消息里,与其对应的
reasoning_details(示例中的 S2)分离; - 对话序列被改变,Gemini 严格的请求校验不接受这种 assistant/tool 配对,于是返回
Request contains an invalid argument.。
换句话说,这不是模型或网关的偶发错误,而是 Open WebUI 侧重组历史后产生的非法请求结构。模型行为本身是非确定性的,但 issue 提供的 snippet 可以在无网络、无 reasoning metadata 的情况下稳定复现边界 bug。
可能相关(issue 评论中机器人列出的关联 issue):
- #31588:连续 tool call 被合并进更早的 assistant 消息,破坏 prompt cache,属于同一类消息边界 bug;
- #24758:
convert_output_to_messages在function_call_output缺失时产生 orphan tool_calls; - #28385:Gemini function calling 场景下中间 reasoning 与 tool-call 内容的处理问题。
环境排查
- 确认 Open WebUI 版本与部署方式:issue 中为 v0.11.4、Docker、
ghcr.io/open-webui/open-webui:latest-slim;如使用其他版本请对照是否已包含 dev 分支的修复。 - 确认是否运行在 Debian 12(或同类 Linux 环境)。
- 确认上游网关地址与模型名称,issue 中为
https://ai-gateway.vercel.sh/v1+google/gemini-3.8-flash。 - 确认是否使用原生工具调用(native tool calling)且存在“并行调用 + 基于结果再次调用”的连续调用模式。
- 检查后端
backend/open_webui/utils/misc.py中convert_output_to_messages()的function_call分支实现。 - Issue 未确认 Ollama、Python、CUDA、PyTorch、显卡版本,这些不必作为必要排查项,除非你的环境另有差异。
解决步骤
- 先确认问题定位:在后端 Python 环境运行 issue 给出的
convert_output_to_messagessnippet。若assert [c["id"] for c in messages[0]["tool_calls"]] == ["A"]失败(第一条 assistant 消息含 A 和 B),说明命中的就是本 issue 的消息合并边界 bug。 - 升级或切换到包含修复的构建。issue 评论中维护者标注该问题“test dev / fixed in dev”,即修复已进入 dev 分支但未给出具体发布版本号;可优先尝试 dev 构建或后续包含该修复的正式版本。
- 如暂时无法升级,可优先尝试 issue 提出的补丁方向:在
backend/open_webui/utils/misc.py的function_call分支中,在收集新的有效 call 之前先 flush 上一步的输出,即加入:elif item_type == 'function_call': if item.get('call_id') not in function_call_ids: continue + flush_tool_outputs() + flush_tool_images() # Collect tool calls to batch into assistant message该 diff 来自 issue 作者,属于“可优先尝试”的修复思路,不是官方发布的确认方案。
- 修改后重启 Open WebUI 服务,重复触发同类工作流(并行搜索后再追加一次搜索),观察是否仍出现 HTTP 400。
验证方法
分两层验证:
- 单元层:重新运行 issue 的 snippet,断言通过,即第一条 assistant 消息的
tool_calls只包含 A,说明后一个 call 不再被合并到上一条消息。 - 接口层:复现相同的用户消息、工具结果与 reasoning metadata,再次向同一网关和模型发起请求。issue 作者的回放结果显示:Original converter 返回 HTTP 400(
Request contains an invalid argument.),Patched converter 返回 HTTP 200 且模型继续请求工具调用。 - 端到端:issue 明确指出“完整浏览器驱动、跑到最终回答”的验证在报告时仍待完成。若你在自己的环境修复,建议走完整 UI 流程直到模型给出最终回答,确认不再出现 400,才视为完全验证。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。
![[Performance]: Non-spec Qwen3.5 CUDA GDN wrapper fallback regressed H200 throughput (fixed by #59735)](https://www.chat-gpts.plus/wp-content/uploads/2026/10/59520-c6b19167-768x403.jpg)
![[Model Support] Kimi K3 Tracking Issue](https://www.chat-gpts.plus/wp-content/uploads/2026/10/50001-de375f68-768x403.jpg)
