[PR #21649] fix: graceful fallback when history.currentId points to an orphan node (infinite spinner) #26182

Open
opened 2026-04-20 06:22:45 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/21649
Author: @ephb
Created: 2/20/2026
Status: 🔄 Open

Base: devHead: fix/resilient-currentid-fallback


📝 Commits (1)

  • 4db72eb fix(Messages): graceful fallback for invalid history.currentId, closes #15189

📊 Changes

1 file changed (+31 additions, -10 deletions)

View changed files

📝 src/lib/components/chat/Messages.svelte (+31 -10)

📄 Description

Pull Request Checklist

  • Target branch: This PR targets the dev branch.
  • Description: Concise description provided below.
  • Testing: Manually tested with a locally-built Docker image using Playwright automation and manual testing on deployment. Reproduction steps and evidence provided below.
  • Code review: Self-reviewed. Single reactive block guard, no new dependencies, no architectural changes.
  • Agentic AI Code: This fix was written and tested by a human. AI tooling was used for assistance, but the logic, testing, and validation were done manually.
  • Git Hygiene: Single atomic commit, rebased on dev.
  • Title Prefix: fix:

Changelog Entry

Description

Fixes a long-standing bug (reported in #15189) where a chat shows an infinite loading spinner and never renders, caused by history.currentId pointing to a partial "orphan" message node that has no role.

This happens when the browser or network drops while OpenWebUI is generating follow-up questions: the backend writes a followUps placeholder into history.messages and updates history.currentId to point at it, before the node has role, content, parentId, or childrenIds. The node looks like:

{
  "23067407-...": {
    "model": "claude-4-sonnet-latest",
    "content": "...",
    "followUps": ["question 1", "question 2"]
  }
}

Messages.svelte's reactive block starts at history.currentId and walks the tree via parentId. Starting from a node with no role means the walk produces nothing, messages = [] on every tick, and the chat spins forever. No console errors appear, making it hard to diagnose.

We confirmed this in production on two separate chats on a deployment, and it matches the exact data structure reported in #15189.

Fixed

  • Messages.svelte: add a guard before the tree-walk that validates history.currentId resolves to a node with a role. If it does not, fall back to the most recent valid terminal message (has role, childrenIds is []) sorted by timestamp. A console.warn is emitted so the recovery is visible in DevTools.

Added

  • Nothing new.

Changed

  • src/lib/components/chat/Messages.svelte: +31 / -10 lines in the reactive $: if (history.currentId) block.

Deprecated / Removed / Security / Breaking Changes

  • None.

Additional Information

How to Reproduce (before fix)

  1. Start a chat and let the LLM finish a response.
  2. While follow-up questions are streaming, close the browser tab or disconnect the network.
  3. Reopen the chat, infinite spinner, no console errors.

Alternatively, import the malformed JSON from issue #15189 - it reliably triggers the bug.

Testing performed

Tested with a locally-built Docker image (openwebui-debug:v0.8.3-fix):

  1. Imported a chat with an artificially injected orphan node (currentId, node with only followUps, no role).
  2. Baseline image (unmodified v0.8.3): chat spins forever. Bug confirmed.
  3. Fixed image (this patch): chat loads correctly. Browser console shows:
    [warn] history.currentId "00000000-..." points to an invalid message (keys: followUps). Falling back to last valid message "471bd8e5-...".
    
    Zero errors. All messages render correctly. Fix confirmed.
  4. Opened several normal (non-corrupted) chats, guard code never triggers, behavior unchanged.

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.


🔄 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/21649 **Author:** [@ephb](https://github.com/ephb) **Created:** 2/20/2026 **Status:** 🔄 Open **Base:** `dev` ← **Head:** `fix/resilient-currentid-fallback` --- ### 📝 Commits (1) - [`4db72eb`](https://github.com/open-webui/open-webui/commit/4db72eb5407bc1f9aa0f3cc80cead80e3121d3f4) fix(Messages): graceful fallback for invalid history.currentId, closes #15189 ### 📊 Changes **1 file changed** (+31 additions, -10 deletions) <details> <summary>View changed files</summary> 📝 `src/lib/components/chat/Messages.svelte` (+31 -10) </details> ### 📄 Description <!-- ⚠️ CRITICAL CHECKS FOR CONTRIBUTORS (READ, DON'T DELETE) ⚠️ 1. Target the `dev` branch. PRs targeting `main` will be automatically closed. 2. Do NOT delete the CLA section at the bottom. It is required for the bot to accept your PR. --> # Pull Request Checklist - [x] **Target branch:** This PR targets the `dev` branch. - [x] **Description:** Concise description provided below. - [x] **Testing:** Manually tested with a locally-built Docker image using Playwright automation and manual testing on deployment. Reproduction steps and evidence provided below. - [x] **Code review:** Self-reviewed. Single reactive block guard, no new dependencies, no architectural changes. - [x] **Agentic AI Code:** This fix was written and tested by a human. AI tooling was used for assistance, but the logic, testing, and validation were done manually. - [x] **Git Hygiene:** Single atomic commit, rebased on `dev`. - [x] **Title Prefix:** `fix:` --- # Changelog Entry ### Description Fixes a long-standing bug (reported in #15189) where a chat shows an **infinite loading spinner** and never renders, caused by `history.currentId` pointing to a partial "orphan" message node that has no `role`. This happens when the browser or network drops while OpenWebUI is generating follow-up questions: the backend writes a `followUps` placeholder into `history.messages` and updates `history.currentId` to point at it, before the node has `role`, `content`, `parentId`, or `childrenIds`. The node looks like: ```json { "23067407-...": { "model": "claude-4-sonnet-latest", "content": "...", "followUps": ["question 1", "question 2"] } } ``` `Messages.svelte`'s reactive block starts at `history.currentId` and walks the tree via `parentId`. Starting from a node with no `role` means the walk produces nothing, `messages = []` on every tick, and the chat spins forever. **No console errors appear**, making it hard to diagnose. We confirmed this in production on two separate chats on a deployment, and it matches the exact data structure reported in #15189. ### Fixed - `Messages.svelte`: add a guard before the tree-walk that validates `history.currentId` resolves to a node with a `role`. If it does not, fall back to the most recent valid terminal message (has `role`, `childrenIds` is `[]`) sorted by timestamp. A `console.warn` is emitted so the recovery is visible in DevTools. ### Added - Nothing new. ### Changed - `src/lib/components/chat/Messages.svelte`: +31 / -10 lines in the reactive `$: if (history.currentId)` block. ### Deprecated / Removed / Security / Breaking Changes - None. --- ### Additional Information - Relates to: #15189 - The fix is purely defensive: it only activates when `currentId` is already invalid. Normal chats are completely unaffected. - If no valid terminal message exists at all (severely corrupted history), a `console.error` is emitted and the chat renders empty - the same visible outcome as before. ### How to Reproduce (before fix) 1. Start a chat and let the LLM finish a response. 2. While follow-up questions are streaming, close the browser tab or disconnect the network. 3. Reopen the chat, infinite spinner, no console errors. Alternatively, import the malformed JSON from issue #15189 - it reliably triggers the bug. ### Testing performed Tested with a locally-built Docker image (`openwebui-debug:v0.8.3-fix`): 1. Imported a chat with an artificially injected orphan node (`currentId`, node with only `followUps`, no `role`). 2. **Baseline image** (unmodified `v0.8.3`): chat spins forever. Bug confirmed. 3. **Fixed image** (this patch): chat loads correctly. Browser console shows: ``` [warn] history.currentId "00000000-..." points to an invalid message (keys: followUps). Falling back to last valid message "471bd8e5-...". ``` Zero errors. All messages render correctly. Fix confirmed. 4. Opened several normal (non-corrupted) chats, guard code never triggers, behavior unchanged. ### 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. --- <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-20 06:22:45 -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#26182