[GH-ISSUE #19777] Stop button disappears when Pipe calls generate_chat_completions internally #34518

Closed
opened 2026-04-25 08:32:36 -05:00 by GiteaMirror · 5 comments
Owner

Originally created by @Yaute7 on GitHub (Dec 5, 2025).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/19777

Check Existing Issues

  • I have searched for any existing and/or related issues.
  • I have searched for any existing and/or related discussions.
  • I have also searched in the CLOSED issues AND CLOSED discussions and found no related items (your issue might already be addressed on the development branch!).
  • I am using the latest version of Open WebUI.

Installation Method

Docker

Open WebUI Version

0.6.36

Ollama Version (if applicable)

No response

Operating System

ubuntu 22.04

Browser (if applicable)

No response

Confirmation

  • I have read and followed all instructions in README.md.
  • I am using the latest version of both Open WebUI and Ollama.
  • I have included the browser console logs.
  • I have included the Docker container logs.
  • I have provided every relevant configuration, setting, and environment variable used in my setup.
  • I have clearly listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc).
  • I have documented step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation. My steps:
  • Start with the initial platform/version/OS and dependencies used,
  • Specify exact install/launch/configure commands,
  • List URLs visited, user input (incl. example values/emails/passwords if needed),
  • Describe all options and toggles enabled or changed,
  • Include any files or environmental changes,
  • Identify the expected and actual result at each stage,
  • Ensure any reasonably skilled user can follow and hit the same issue.

Expected Behavior

The Stop button should remain visible during the entire Pipe execution, including internal preprocessing calls to generate_chat_completions, allowing users to cancel at any time - just like it works when using models directly.

Actual Behavior

Stop button disappears immediately when a Pipe function calls generate_chat_completions internally for preprocessing (like query classification). The button is replaced by the microphone icon even though the request is still processing.

The Stop button works correctly when using a model directly (without the Pipe)

Steps to Reproduce

Create a Pipe function with this minimal code:
- Go to Workspace → Functions → Add Function
- Paste this code:

from open_webui.main import generate_chat_completions
from open_webui.models.users import Users

class Pipe:
    def __init__(self):
        self.type = "pipe"
        self.id = "test-router"
        self.name = "Test Router"

    def pipes(self):
        return [{"id": "router", "name": "🧠 Router Test"}]

    async def pipe(self, body: dict, __user__: dict, __request__, __event_emitter__=None, __task__=None, __metadata__=None):
        if __task__ is not None:
            return

        user = Users.get_user_by_id(__user__["id"])

        # Internal LLM call for classification (THIS CAUSES THE BUG)
        await generate_chat_completions(
            request=__request__,
            form_data={
                "model": "YOUR_MODEL_NAME",  # Replace with your model
                "messages": [{"role": "user", "content": "Say hello"}],
                "stream": False,
            },
            user=user,
        )

        # Main response
        body["model"] = "YOUR_MODEL_NAME"  # Replace with your model
        return await generate_chat_completions(
            request=__request__, form_data=body, user=user
        )

3. Enable the Pipe: Toggle it ON in the Functions list
4. Start a new chat: Select "🧠 Router Test" as the model
5. Send any message: e.g., "Hello"
6. Observe:
  - EXPECTED: Stop button remains visible during processing
  - ACTUAL: Stop button disappears immediately, replaced by microphone icon
7. Compare with direct model:
  - Select a regular model (not the Pipe)
  - Send a message
  - RESULT: Stop button remains visible correctly

### Logs & Screenshots

<img width="1356" height="1127" alt="Image" src="https://github.com/user-attachments/assets/f311c21e-8f1b-406e-8d46-46b97309792c" />

### Additional Information

_No response_
Originally created by @Yaute7 on GitHub (Dec 5, 2025). Original GitHub issue: https://github.com/open-webui/open-webui/issues/19777 ### Check Existing Issues - [x] I have searched for any existing and/or related issues. - [x] I have searched for any existing and/or related discussions. - [x] I have also searched in the CLOSED issues AND CLOSED discussions and found no related items (your issue might already be addressed on the development branch!). - [x] I am using the latest version of Open WebUI. ### Installation Method Docker ### Open WebUI Version 0.6.36 ### Ollama Version (if applicable) _No response_ ### Operating System ubuntu 22.04 ### Browser (if applicable) _No response_ ### Confirmation - [x] I have read and followed all instructions in `README.md`. - [x] I am using the latest version of **both** Open WebUI and Ollama. - [x] I have included the browser console logs. - [x] I have included the Docker container logs. - [x] I have **provided every relevant configuration, setting, and environment variable used in my setup.** - [x] I have clearly **listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup** (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc). - [x] I have documented **step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation**. My steps: - Start with the initial platform/version/OS and dependencies used, - Specify exact install/launch/configure commands, - List URLs visited, user input (incl. example values/emails/passwords if needed), - Describe all options and toggles enabled or changed, - Include any files or environmental changes, - Identify the expected and actual result at each stage, - Ensure any reasonably skilled user can follow and hit the same issue. ### Expected Behavior The Stop button should remain visible during the entire Pipe execution, including internal preprocessing calls to generate_chat_completions, allowing users to cancel at any time - just like it works when using models directly. ### Actual Behavior Stop button disappears immediately when a Pipe function calls `generate_chat_completions` internally for preprocessing (like query classification). The button is replaced by the microphone icon even though the request is still processing. The Stop button works correctly when using a model directly (without the Pipe) ### Steps to Reproduce **Create a Pipe function** with this minimal code: - Go to Workspace → Functions → Add Function - Paste this code: ```python from open_webui.main import generate_chat_completions from open_webui.models.users import Users class Pipe: def __init__(self): self.type = "pipe" self.id = "test-router" self.name = "Test Router" def pipes(self): return [{"id": "router", "name": "🧠 Router Test"}] async def pipe(self, body: dict, __user__: dict, __request__, __event_emitter__=None, __task__=None, __metadata__=None): if __task__ is not None: return user = Users.get_user_by_id(__user__["id"]) # Internal LLM call for classification (THIS CAUSES THE BUG) await generate_chat_completions( request=__request__, form_data={ "model": "YOUR_MODEL_NAME", # Replace with your model "messages": [{"role": "user", "content": "Say hello"}], "stream": False, }, user=user, ) # Main response body["model"] = "YOUR_MODEL_NAME" # Replace with your model return await generate_chat_completions( request=__request__, form_data=body, user=user ) 3. Enable the Pipe: Toggle it ON in the Functions list 4. Start a new chat: Select "🧠 Router Test" as the model 5. Send any message: e.g., "Hello" 6. Observe: - EXPECTED: Stop button remains visible during processing - ACTUAL: Stop button disappears immediately, replaced by microphone icon 7. Compare with direct model: - Select a regular model (not the Pipe) - Send a message - RESULT: Stop button remains visible correctly ### Logs & Screenshots <img width="1356" height="1127" alt="Image" src="https://github.com/user-attachments/assets/f311c21e-8f1b-406e-8d46-46b97309792c" /> ### Additional Information _No response_
GiteaMirror added the bug label 2026-04-25 08:32:36 -05:00
Author
Owner

@owui-terminator[bot] commented on GitHub (Dec 5, 2025):

🔍 Similar Issues Found

I found some existing issues that might be related to this one. Please check if any of these are duplicates or contain helpful solutions:

  1. #19563 issue:
    by naruto7g • Nov 28, 2025 • bug

  2. #19211 issue:
    by Byrnes9 • Nov 16, 2025 • bug

  3. #15638 issue:
    by PaulX1029 • Jul 11, 2025 • bug

  4. #17387 issue:
    by abxis • Sep 12, 2025 • bug

  5. #17389 issue:
    by abxis • Sep 12, 2025 • bug

Show 5 more related issues
  1. #17388 issue:
    by abxis • Sep 12, 2025 • bug

  2. #17392 issue:
    by abxis • Sep 12, 2025 • bug

  3. #17390 issue:
    by abxis • Sep 12, 2025 • bug

  4. #17391 issue:
    by abxis • Sep 12, 2025 • bug

  5. #17393 issue:
    by abxis • Sep 12, 2025 • bug


💡 Tips:

  • If this is a duplicate, please consider closing this issue and adding any additional details to the existing one
  • If you found a solution in any of these issues, please share it here to help others

This comment was generated automatically by a bot. Please react with a 👍 if this comment was helpful, or a 👎 if it was not.

<!-- gh-comment-id:3616446022 --> @owui-terminator[bot] commented on GitHub (Dec 5, 2025): 🔍 **Similar Issues Found** I found some existing issues that might be related to this one. Please check if any of these are duplicates or contain helpful solutions: 1. [#19563](https://github.com/open-webui/open-webui/issues/19563) **issue:** *by naruto7g • Nov 28, 2025 • `bug`* 2. [#19211](https://github.com/open-webui/open-webui/issues/19211) **issue:** *by Byrnes9 • Nov 16, 2025 • `bug`* 3. [#15638](https://github.com/open-webui/open-webui/issues/15638) **issue:** *by PaulX1029 • Jul 11, 2025 • `bug`* 4. [#17387](https://github.com/open-webui/open-webui/issues/17387) **issue:** *by abxis • Sep 12, 2025 • `bug`* 5. [#17389](https://github.com/open-webui/open-webui/issues/17389) **issue:** *by abxis • Sep 12, 2025 • `bug`* <details> <summary>Show 5 more related issues</summary> 6. [#17388](https://github.com/open-webui/open-webui/issues/17388) **issue:** *by abxis • Sep 12, 2025 • `bug`* 7. [#17392](https://github.com/open-webui/open-webui/issues/17392) **issue:** *by abxis • Sep 12, 2025 • `bug`* 8. [#17390](https://github.com/open-webui/open-webui/issues/17390) **issue:** *by abxis • Sep 12, 2025 • `bug`* 9. [#17391](https://github.com/open-webui/open-webui/issues/17391) **issue:** *by abxis • Sep 12, 2025 • `bug`* 10. [#17393](https://github.com/open-webui/open-webui/issues/17393) **issue:** *by abxis • Sep 12, 2025 • `bug`* </details> --- 💡 **Tips:** - If this is a duplicate, please consider closing this issue and adding any additional details to the existing one - If you found a solution in any of these issues, please share it here to help others *This comment was generated automatically by a bot.* Please react with a 👍 if this comment was helpful, or a 👎 if it was not.
Author
Owner

@Classic298 commented on GitHub (Dec 5, 2025):

Please give your issue a title

<!-- gh-comment-id:3616488472 --> @Classic298 commented on GitHub (Dec 5, 2025): Please give your issue a title
Author
Owner

@rgaricano commented on GitHub (Dec 5, 2025):

When a Pipe function calls generate_chat_completions internally for preprocessing, it triggers the same event emission flow as a regular chat completion. The frontend receives these completion events and updates its state, causing the Stop button condition to evaluate to false.

You can bypass this behaviour instead of using generate_chat_completions internally, make direct HTTP requests to the model APIcalling the API directly:

import requests
import json

class Pipe:
    class Valves(BaseModel):
        urlIdx: int = 0  # Default to first configured URL

    async def pipe(self, body: dict, __user__: dict, __request__, __event_emitter__=None, __task__=None, __metadata__=None):
        # Get the WebUI URL from app state
        webui_url = __request__.app.state.config.WEBUI_URL

        # Internal LLM call via direct API using the WebUI URL
        response = requests.post(
            url=f"{webui_url}/openai/chat/completions",  # Use OpenAI-compatible endpoint
            headers={
                "Authorization": f"Bearer {__request__.app.state.config.OPENAI_API_KEYS[self.valves.urlIdx]}",
                "Content-Type": "application/json"
            },
            json={
                "model": "YOUR_MODEL_NAME",
                "messages": [{"role": "user", "content": "Say hello"}],
                "stream": False
            }
        )
        classification_result = response.json()

        # Main response using the normal pipe flow
        body["model"] = "YOUR_MODEL_NAME"
        return await generate_chat_completions(
            request=__request__, 
            form_data=body, 
            user=user
        )

(There are other ways

  • Use a Custom Event Emitter
  • Manual Task State Management
  • Use the Task System

but this is the easier and with less possible "side-effects" )

<!-- gh-comment-id:3617569741 --> @rgaricano commented on GitHub (Dec 5, 2025): When a Pipe function calls generate_chat_completions internally for preprocessing, it triggers the same event emission flow as a regular chat completion. The frontend receives these completion events and updates its state, causing the Stop button condition to evaluate to false. You can bypass this behaviour instead of using `generate_chat_completions` internally, make direct HTTP requests to the model APIcalling the API directly: ``` import requests import json class Pipe: class Valves(BaseModel): urlIdx: int = 0 # Default to first configured URL async def pipe(self, body: dict, __user__: dict, __request__, __event_emitter__=None, __task__=None, __metadata__=None): # Get the WebUI URL from app state webui_url = __request__.app.state.config.WEBUI_URL # Internal LLM call via direct API using the WebUI URL response = requests.post( url=f"{webui_url}/openai/chat/completions", # Use OpenAI-compatible endpoint headers={ "Authorization": f"Bearer {__request__.app.state.config.OPENAI_API_KEYS[self.valves.urlIdx]}", "Content-Type": "application/json" }, json={ "model": "YOUR_MODEL_NAME", "messages": [{"role": "user", "content": "Say hello"}], "stream": False } ) classification_result = response.json() # Main response using the normal pipe flow body["model"] = "YOUR_MODEL_NAME" return await generate_chat_completions( request=__request__, form_data=body, user=user ) ``` (There are other ways - Use a Custom Event Emitter - Manual Task State Management - Use the Task System but this is the easier and with less possible "side-effects" )
Author
Owner

@Yaute7 commented on GitHub (Dec 5, 2025):

@rgaricano Thanks for your help! I followed your advice and made progress:

What I did:

  1. Changed internal LLM calls (for classification/routing) to direct HTTP requests to my LiteLLM proxy - this works well
  2. Final response still uses generate_chat_completions for proper streaming

What I found:
The Stop button issue is specifically caused by re-injecting session_id into the body before calling generate_chat_completions.

In my Pipe, I was doing:

if __metadata__:
    body["chat_id"] = __metadata__.get("chat_id")
    body["id"] = __metadata__.get("message_id")
    body["session_id"] = __metadata__.get("session_id")  # ← THIS breaks the Stop button

Test results:
| Metadata                  | Stop button | Sources/citations work                   |
|---------------------------|-------------|------------------------------------------|
| All 3 injected            |  Hidden    |  Yes                                    |
| Only chat_id + message_id |  Visible   |  Yes                                    |
| Only session_id removed   |  Visible   | ⚠️ Partial (links in text don't resolve) |

Question: Is there a way to keep session_id for citation linking without breaking the Stop button? Or is this a bug that should be reported separately?

Thanks again for your guidance!
<!-- gh-comment-id:3617767804 --> @Yaute7 commented on GitHub (Dec 5, 2025): @rgaricano Thanks for your help! I followed your advice and made progress: **What I did:** 1. ✅ Changed internal LLM calls (for classification/routing) to direct HTTP requests to my LiteLLM proxy - this works well 2. ✅ Final response still uses `generate_chat_completions` for proper streaming **What I found:** The Stop button issue is specifically caused by **re-injecting `session_id`** into the body before calling `generate_chat_completions`. In my Pipe, I was doing: ```python if __metadata__: body["chat_id"] = __metadata__.get("chat_id") body["id"] = __metadata__.get("message_id") body["session_id"] = __metadata__.get("session_id") # ← THIS breaks the Stop button Test results: | Metadata | Stop button | Sources/citations work | |---------------------------|-------------|------------------------------------------| | All 3 injected | ❌ Hidden | ✅ Yes | | Only chat_id + message_id | ✅ Visible | ✅ Yes | | Only session_id removed | ✅ Visible | ⚠️ Partial (links in text don't resolve) | Question: Is there a way to keep session_id for citation linking without breaking the Stop button? Or is this a bug that should be reported separately? Thanks again for your guidance!
Author
Owner

@tjbck commented on GitHub (Dec 5, 2025):

Internal functions should not be used here.

<!-- gh-comment-id:3618010850 --> @tjbck commented on GitHub (Dec 5, 2025): Internal functions should not be used here.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#34518