fix: chat corruption (openweb-ui#26668)#26971
Open
intdel wants to merge 1 commit into
Open
Conversation
open-webui#26668) Deleting a user message while its reply was still streaming corrupted the chat: after the generation finished, only the streamed reply survived on reload and the rest of the history became unreachable. Root cause: deleting a message did not cancel the in-flight generation. The backend task kept running and, on completion, upserted the deleted assistant message with no resolvable parent — recreating it as an orphan root and pointing currentId at it. createMessagesList walks parentId from currentId, so the broken parent chain stranded the prior conversation. Three fixes: 1. Frontend (Messages.svelte): when the message being deleted (or one of its reply children) is the not-yet-done assistant reply at currentId, call stopResponse(false) first to cancel the backend task. Gate on the message done-state (the codebase's own isGenerating heuristic) rather than the `generating` flag, which is only set in the MoA merge path. stopResponse is threaded through from Chat.svelte as a prop. 2. Backend (chats.py upsert_message_to_chat_by_id_and_message_id): if a stale completion upsert arrives for a message that is no longer in the chat with no resolvable parent (parent deleted, or no surviving message references it in childrenIds), skip the write instead of resurrecting it as an orphan root. Normal flow is unaffected — the user message is persisted before generation, so the assistant upsert resolves a live parent or hits the existing-message merge branch. 3. Backend: only advance currentId to the upserted message when its parentId is None or exists in the messages map, so currentId can never point at a message with a broken parent chain.
Collaborator
|
thanks for the video! |
Collaborator
|
LGTM! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request Checklist
Note to first-time contributors: Please open a discussion post in Discussions to discuss your idea/fix with the community before creating a pull request, and describe your changes before submitting a pull request.
This is to ensure large feature PRs are discussed with the community first, before starting work on it. If the community does not want this feature or it is not relevant for Open WebUI as a project, it can be identified in the discussion before working on the feature and submitting the PR.
Before submitting, make sure you've checked the following:
Closes #___/Relates to #___. If one does not exist, create one first. PRs without a linked issue or discussion may be closed without review.devbranch. PRs targetingmainwill be immediately closed.dev, and contains no unrelated commits.Changelog Entry
Description
Deleting a user message while its reply was still streaming corrupted the chat: after the generation finished, only the streamed reply survived on reload and the rest of the history became unreachable.
Root cause: deleting a message did not cancel the in-flight generation. The backend task kept running and, on completion, upserted the deleted assistant message with no resolvable parent — recreating it as an orphan root and pointing currentId at it. createMessagesList walks parentId from currentId, so the broken parent chain stranded the prior conversation.
Three fixes:
Frontend (Messages.svelte): when the message being deleted (or one of its reply children) is the not-yet-done assistant reply at currentId, call stopResponse(false) first to cancel the backend task. Gate on the message done-state (the codebase's own isGenerating heuristic) rather than the
generatingflag, which is only set in the MoA merge path. stopResponse is threaded through from Chat.svelte as a prop.Backend (chats.py upsert_message_to_chat_by_id_and_message_id): if a stale completion upsert arrives for a message that is no longer in the chat with no resolvable parent (parent deleted, or no surviving message references it in childrenIds), skip the write instead of resurrecting it as an orphan root. Normal flow is unaffected — the user message is persisted before generation, so the assistant upsert resolves a live parent or hits the existing-message merge branch.
Backend: only advance currentId to the upserted message when its parentId is None or exists in the messages map, so currentId can never point at a message with a broken parent chain.
Fixed
Additional Information
Screenshots or Videos
Screen.Recording.2026-07-10.102926.mp4
Contributor License Agreement
Note
Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in.