mirror of
https://github.com/open-webui/open-webui.git
synced 2026-07-15 21:19:39 -05:00
[GH-ISSUE #24758] issue: convert_output_to_messages produces orphan tool_calls when function_call_output is missing from stored output #107391
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @marcodigitalhub on GitHub (May 15, 2026).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/24758
Check Existing Issues
Installation Method
Git Clone
Open WebUI Version
0.9.5
Ollama Version (if applicable)
No response
Operating System
macOS and Ubuntu 23.04
Browser (if applicable)
No response
Confirmation
README.md.Expected Behavior
When resuming a chat that previously triggered tool calls, the conversation should continue normally even if some tool results were never stored in the output field (for example, because the knowledge base was updated between turns).
Actual Behavior
The resumed chat fails with a 400 error from the LLM provider. The conversation history sent to the model contains assistant messages with tool_calls that have no matching tool role messages after them. Providers that enforce strict pairing (AWS Bedrock Converse, Anthropic) reject this with:
Steps to Reproduce
Deploy Open WebUI connected to AWS Bedrock via the bedrock-access-gateway (or any strict provider that enforces tool_use/tool_result pairing).
Enable native function calling (
function_calling: nativein model params) and attach at least one tool to the model (a knowledge base lookup tool works well for this).Start a new chat and send a message that triggers the tool. Wait for the assistant to respond using the tool. At this point the DB stores the assistant's
outputfield withfunction_callandfunction_call_outputitems.Now update the knowledge base (add or remove a file). This causes the tool's internal state to change.
In the same chat, send a follow-up message. Open WebUI loads the message history from the DB via
load_messages_from_db, passes it throughprocess_messages_with_output, which callsconvert_output_to_messages.The function fails with the 400 ValidationException shown above.
The root cause is in
misc.pyinconvert_output_to_messages. The function collects function_call items intopending_tool_callsand only flushes them into an assistant message when it encounters afunction_call_output. If afunction_call_outputis missing from the stored output (because it was never written, or was lost during the KB update), the finalflush_pending()at line 280 emits an assistant message withtool_callsbut no subsequent tool role message follows it.You can also reproduce this programmatically without the UI by saving a chat with orphan function_call items in the output field and then sending a completion request with
chat_idset to that chat's ID.Logs & Screenshots
Error returned by the API:
Additional Information
The fix is straightforward. After
flush_pending()at the end ofconvert_output_to_messages, scan the produced message list and strip anytool_callswhose id has no matchingtool_call_idin a subsequent tool role message. If stripping leaves an assistant message with empty content and notool_calls, drop it entirely. Well-formed sequences are unaffected since the check is a no-op when all ids match.I have a working patch, tested in local and AWS setups, and can open a PR targeting dev if this approach sounds reasonable.
@owui-terminator[bot] commented on GitHub (May 15, 2026):
🔍 Related Issues Found
I found some existing issues that might be related. Please check if any of these are duplicates or contain helpful solutions:
🟣 #21471 issue: v0.8.2 Unexpected tool_use_id
Reports a tool-use pairing problem after native tool calling that blocks follow-up messages in Claude/Litellm-style providers. While the exact cause differs, it is closely related to malformed tool call history causing provider validation errors.
by mustard123 ·
bug🟣 #12214 issue: Tool Calls result overrides previous tools messages sent
Describes native tool calling producing incorrect/overwritten tool message handling in the chat history. This is related to the same general area of assistant/tool message sequencing and message reconstruction.
by ivanwong1989 ·
bug🟣 #14157 issue: Switching models in chat does not deselect previously selected tools
About tool selection/state persisting incorrectly across model switches, which is adjacent to the chat/tool state handling involved here. It is less direct, but still touches the same tool-context lifecycle.
by jrkropp ·
bug,help wanted,testing wanted💡 If your issue is a duplicate, please close it and add any additional details to the existing issue instead.
This comment was generated automatically. React with 👍 if helpful, 👎 if not.
@Classic298 commented on GitHub (May 15, 2026):
Why is function call output missing?
That's the actual question here
Do you have any custom filters or pipes?
@marcodigitalhub commented on GitHub (May 15, 2026):
@Classic298 Why is function_call_output missing?:
From what we've traced, it happens when the user updates the knowledge base and then continues an existing chat. The frontend rewrites the message history on KB changes and the rewrite doesn't always preserve the full output structure. The function_call items survive but their matching
function_call_outputentries get lost.We've also seen it when a tool call is interrupted (user cancels or connection drops mid-execution). The
function_callgets written first as a streaming event, but the result never arrives. Either way,convert_output_to_messagesshould handle incomplete output gracefully. An orphantool_callswith no matching result is never valid for any provider, so stripping it at reconstruction time seems like the right safety net.Do you have any custom filters or pipes?
Just one global filter for content safety (Bedrock Guardrails). It only inspects user input and model output text, doesn't touch message history or
tool_callsat all. No custom pipes. We use MCP tool servers for tools.The issue reproduces with the filter disabled too. The root cause is entirely in how
convert_output_to_messageshandles incomplete output arrays.@Classic298 commented on GitHub (May 15, 2026):
investigating
@Classic298 commented on GitHub (May 15, 2026):
Related but not direct fix for your report: https://github.com/open-webui/open-webui/pull/24617 https://github.com/open-webui/open-webui/pull/24799
@Classic298 commented on GitHub (May 15, 2026):
@marcodigitalhub testing wanted https://github.com/open-webui/open-webui/pull/24798
@marcodigitalhub commented on GitHub (May 16, 2026):
@Classic298 Tested locally against four scenarios. Without the fix, three of four fail, orphan
tool_callsurvives, all-orphan turns leaktool_useids with notool_result, and orphan calls beside text content still produce unbalanced output. With the fix, all four produce a balanced sequence and the well-formed case is unchanged.LGTM. One suggestion: a unit test in the repo would lock this in against future regressions. Happy to open a follow-up PR with the four cases above as
pytestparametrized tests if you want.@Classic298 commented on GitHub (May 16, 2026):
@marcodigitalhub thanks we have an internal unit test repo i already added it there