[PR #22235] [CLOSED] fix: prevent streaming tool call function name duplication #42192

Closed
opened 2026-04-25 14:11:06 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/22235
Author: @Classic298
Created: 3/4/2026
Status: Closed

Base: devHead: fix/streaming-tool-call-name-dedup


📝 Commits (2)

  • c8687e4 fix: prevent streaming tool call function name duplication
  • 3aebc70 Update middleware.py

📊 Changes

1 file changed (+60 additions, -2 deletions)

View changed files

📝 backend/open_webui/utils/middleware.py (+60 -2)

📄 Description

fix: prevent streaming tool call function name and argument duplication

Problem

Some models (notably GPT-5, GPT-5.1, and newer OpenAI models) re-send the function name and/or complete arguments in follow-up streaming deltas for the same tool call index. This causes two issues:

  1. Name duplication: The function name gets doubled (e.g. my_server_search becomes my_server_searchmy_server_search) because the streaming delta handler accumulates names with +=. The doubled name doesn't match any registered tool, so the tool silently fails — the user sees "Tool Executed" but nothing actually ran.

  2. Argument concatenation: When a model sends multiple complete JSON argument objects under the same tool call index (observed with GPT-5.4 calling search tools with multiple queries), the += accumulation produces concatenated JSON like {"query":"A","count":5}{"query":"B","count":5} which is not valid JSON and fails to parse.

Fix

Name deduplication: Changed the name accumulation to a conditional assignment — the name is only set if it hasn't been set yet. This is safe because:

  • Normal case: name arrives in the first delta and is already set via the initial append
  • Edge case (empty first delta): the setdefault("name", "") at entry creation sets it to "", which is falsy, so a subsequent delta correctly sets it
  • GPT-5/5.1 re-send case: the conditional skips it because the name is already set

Argument expansion: Added a pre-processing step before tool call execution that detects concatenated JSON objects in a tool call's arguments using json.JSONDecoder.raw_decode(). If multiple valid JSON objects are found back-to-back, the single tool call entry is expanded into separate entries — one per JSON object — so each gets executed independently. This:

  • Doesn't touch the streaming accumulation path, so normal fragmented argument streaming works as before
  • Falls through transparently for single-object arguments (the common case)
  • Lets downstream ast.literal_eval / json.loads handle non-JSON formats as before

Affected models

Model Name doubled Args concatenated
GPT-5.1 Always Sometimes
GPT-5 Sometimes Sometimes
GPT-5.2+ Observed Observed
GPT-4o Never Never
Claude Never Never
  • #22177 — Streaming tool call function name doubled by delta accumulation
  • #16138 — Tools names are doubled when calling
  • #19656 — Tool call response tokens are duplicated

Contributor License Agreement

By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms.

Note

Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/22235 **Author:** [@Classic298](https://github.com/Classic298) **Created:** 3/4/2026 **Status:** ❌ Closed **Base:** `dev` ← **Head:** `fix/streaming-tool-call-name-dedup` --- ### 📝 Commits (2) - [`c8687e4`](https://github.com/open-webui/open-webui/commit/c8687e49ee5e477bd679d73747ef6dd66997a37e) fix: prevent streaming tool call function name duplication - [`3aebc70`](https://github.com/open-webui/open-webui/commit/3aebc70d2de0e6f69a1d7e3799f00d214d841f68) Update middleware.py ### 📊 Changes **1 file changed** (+60 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `backend/open_webui/utils/middleware.py` (+60 -2) </details> ### 📄 Description ## fix: prevent streaming tool call function name and argument duplication ### Problem Some models (notably GPT-5, GPT-5.1, and newer OpenAI models) re-send the function name and/or complete arguments in follow-up streaming deltas for the same tool call index. This causes two issues: 1. **Name duplication**: The function name gets doubled (e.g. my_server_search becomes my_server_searchmy_server_search) because the streaming delta handler accumulates names with +=. The doubled name doesn't match any registered tool, so the tool silently fails — the user sees "Tool Executed" but nothing actually ran. 2. **Argument concatenation**: When a model sends multiple complete JSON argument objects under the same tool call index (observed with GPT-5.4 calling search tools with multiple queries), the += accumulation produces concatenated JSON like {"query":"A","count":5}{"query":"B","count":5} which is not valid JSON and fails to parse. ### Fix **Name deduplication**: Changed the name accumulation to a conditional assignment — the name is only set if it hasn't been set yet. This is safe because: - Normal case: name arrives in the first delta and is already set via the initial append - Edge case (empty first delta): the setdefault("name", "") at entry creation sets it to "", which is falsy, so a subsequent delta correctly sets it - GPT-5/5.1 re-send case: the conditional skips it because the name is already set **Argument expansion**: Added a pre-processing step before tool call execution that detects concatenated JSON objects in a tool call's arguments using json.JSONDecoder.raw_decode(). If multiple valid JSON objects are found back-to-back, the single tool call entry is expanded into separate entries — one per JSON object — so each gets executed independently. This: - Doesn't touch the streaming accumulation path, so normal fragmented argument streaming works as before - Falls through transparently for single-object arguments (the common case) - Lets downstream ast.literal_eval / json.loads handle non-JSON formats as before ### Affected models | Model | Name doubled | Args concatenated | |-------|-------------|-------------------| | GPT-5.1 | Always | Sometimes | | GPT-5 | Sometimes | Sometimes | | GPT-5.2+ | Observed | Observed | | GPT-4o | Never | Never | | Claude | Never | Never | ### Related issues - #22177 — Streaming tool call function name doubled by delta accumulation - #16138 — Tools names are doubled when calling - #19656 — Tool call response tokens are duplicated ### Contributor License Agreement <!-- 🚨 DO NOT DELETE THE TEXT BELOW 🚨 Keep the "Contributor License Agreement" confirmation text intact. Deleting it will trigger the CLA-Bot to INVALIDATE your PR. --> By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms. > [!NOTE] > Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-25 14:11:06 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#42192