open-webui / open-webui/open-webui
issue: ask_user is offered in temporary chats, where answering it discards the chat
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 153k
- Forks
- 22.3k
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 194
Description
Before Submitting
- I searched open and closed issues and discussions for an existing report.
- I checked whether this is already fixed on the
devbranch or latest source. - I understand that maintainers want a well-written issue before any code pull request.
- I am using the latest available version of Open WebUI for my install method.
- This is not a security vulnerability.
Installation Method
Git Clone
Open WebUI Version
dev, commit a93c5080380447e3ab9113cacb73b61c57cbc308
Operating System
Ubuntu
Browser
Firefox
Ollama Version
No response
Summary
In a temporary chat, the model can still call the built in ask_user tool. The question card renders and can be answered, but submitting the answer fails and the temporary chat is then discarded, so everything in it is lost. This is consistently reproducible.
Expected Behavior
ask_user needs a saved chat to resolve an answer, so it should not be offered in a temporary chat at all, the way the task management tools already handle it. Nothing in the conversation should be lost.
Actual Behavior
The tool is offered, the model calls it, and the card renders and accepts answers. Submitting them returns 401 from the resolve endpoint, and the temporary chat then disappears and the conversation is gone.
Steps to Reproduce
- Start a temporary chat with a model using native function calling.
- Send a prompt that makes the model call
ask_user, for example:Ask me 2 quick questions about my homelab setup using the ask_user tool, each with 2-3 answer options. - Answer the questions on the card and submit.
- The submission fails and the temporary chat is discarded.
Logs, Screenshots, and Config
The failing request is a POST to /api/v1/chats/{id}/messages/{message_id}/resolve returning 401.
Additional Information
Root cause, pinned to commit a93c5080380447e3ab9113cacb73b61c57cbc308.
Answering an ask_user call is resolved entirely against stored state. resolve_tool_call_output loads the chat by id, finds the pending function_call on that message, appends the answers as a function_call_output, and the completion is then resumed from the stored chat. A temporary chat is never written to the database, so the first lookup fails and the endpoint returns 401.
The tool is nevertheless offered unconditionally when the builtin is enabled:
if is_builtin_tool_enabled('user_input', True):
builtin_functions.append(ask_user)
The task management tools in the same function already handle this case, and their comment states the reason:
# Task management - break down complex work into trackable steps
# Task state is stored on the chats row; local/channel IDs do not have one.
if is_builtin_tool_enabled('tasks') and is_saved_chat_id(metadata.get('chat_id')):
builtin_functions.extend([create_tasks, update_task])
tools.py#L738-L741. ask_user depends on the same stored state, so the same guard applies:
- if is_builtin_tool_enabled('user_input', True):
+ if is_builtin_tool_enabled('user_input', True) and is_saved_chat_id(metadata.get('chat_id')):
builtin_functions.append(ask_user)
is_saved_chat_id is already imported in that file. One detail to handle: metadata is bound a little below this block, at tools.py#L585, so either the ask_user block moves below that assignment or the assignment moves above it.
Why the chat is lost rather than just erroring: the frontend's error handler for the failed resolve calls loadChat() (Chat.svelte#L560, and the same pattern for cancelling at L578), and loadChat cannot find a temporary chat, so it falls into await goto('/') at Chat.svelte#L2251 and the conversation is discarded. Not injecting the tool makes that path unreachable for this case, which is why the injection guard alone should be enough.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in backend/open_webui/utils/tools.py at the builtin tool registration and compare the existing saved-chat guard for task tools with the ask_user path. Reproduce the temporary-chat flow, then verify that ask_user is unavailable there while it remains usable in saved chats; Chat.svelte documents the discard path caused by the failed resolve.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, frontend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100