[PR #21648] [CLOSED] fix(Messages): graceful fallback when history.currentId points to an orphan node #49229

Closed
opened 2026-04-30 01:33:23 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

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

Base: mainHead: fix/resilient-currentid-fallback


📝 Commits (1)

  • 1592ab3 fix(Messages): graceful fallback when history.currentId is an orphan node

📊 Changes

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

View changed files

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

📄 Description

Fixes #15189

Problem

When the browser closes (or the network drops) while OpenWebUI is generating follow-up questions, the backend writes a partial placeholder node into history.messages and updates history.currentId to point at it — before the node has role, content, parentId, or childrenIds.

The resulting orphan looks like:

{
  "23067407-327f-4167-bac6-5804080aed15": {
    "model": "claude-4-sonnet-latest",
    "content": "...",
    "followUps": ["question 1", "question 2"]
  }
}

Messages.svelte's reactive block starts at history.currentId and walks backwards through parentId links to build the message list. Starting from a node with no role means the walk finds nothing valid, so the component emits messages = [] on every tick — the chat shows an infinite spinner and never loads, even after hours. No console errors appear, making this hard to diagnose.

This is the exact scenario reported in #15189 (and confirmed in the wild on our own deployment with a second independently-encountered instance).

Fix

Before starting the tree-walk, validate that history.currentId resolves to a message that has a role property. If it does not, find the most recent valid terminal message (has role, childrenIds is an empty array) sorted by timestamp, and use that as the starting point instead.

A console.warn is emitted so the fallback is visible in DevTools without breaking the UX. If no valid terminal message exists at all, a console.error is emitted and the chat renders empty (same behavior as before, but without the infinite reactive loop).

How to reproduce

  1. Start a chat and wait for a full LLM response + follow-up generation to begin.
  2. While follow-ups are streaming, close the browser tab or kill the network.
  3. Reopen the chat → infinite spinner.

Or, inject an orphan manually into the DB (see issue #15189 for a ready-made JSON import that reliably triggers it).

Testing

  • Tested with Playwright against a locally-built Docker image.
  • Baseline image (v0.8.3-baseline, unmodified): chat spins forever.
  • Fixed image (v0.8.3-resilient, this patch): chat loads, browser console shows the console.warn fallback message, zero errors.
  • Verified that normal (non-corrupted) chats are completely unaffected — the guard code is never triggered.

Scope

Single file changed: src/lib/components/chat/Messages.svelte (+34 / -10 lines). No backend changes, no new dependencies.


🔄 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/21648 **Author:** [@ephb](https://github.com/ephb) **Created:** 2/20/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/resilient-currentid-fallback` --- ### 📝 Commits (1) - [`1592ab3`](https://github.com/open-webui/open-webui/commit/1592ab3663b97a7046da16ed367f6000989cf545) fix(Messages): graceful fallback when history.currentId is an orphan node ### 📊 Changes **1 file changed** (+34 additions, -10 deletions) <details> <summary>View changed files</summary> 📝 `src/lib/components/chat/Messages.svelte` (+34 -10) </details> ### 📄 Description ## Closes / Related Fixes #15189 ## Problem When the browser closes (or the network drops) while OpenWebUI is generating follow-up questions, the backend writes a partial placeholder node into `history.messages` and updates `history.currentId` to point at it — **before** the node has `role`, `content`, `parentId`, or `childrenIds`. The resulting orphan looks like: ```json { "23067407-327f-4167-bac6-5804080aed15": { "model": "claude-4-sonnet-latest", "content": "...", "followUps": ["question 1", "question 2"] } } ``` `Messages.svelte`'s reactive block starts at `history.currentId` and walks backwards through `parentId` links to build the message list. Starting from a node with no `role` means the walk finds nothing valid, so the component emits `messages = []` on every tick — the chat shows an **infinite spinner** and never loads, even after hours. No console errors appear, making this hard to diagnose. This is the exact scenario reported in #15189 (and confirmed in the wild on our own deployment with a second independently-encountered instance). ## Fix Before starting the tree-walk, validate that `history.currentId` resolves to a message that has a `role` property. If it does not, find the most recent **valid terminal message** (has `role`, `childrenIds` is an empty array) sorted by timestamp, and use that as the starting point instead. A `console.warn` is emitted so the fallback is visible in DevTools without breaking the UX. If no valid terminal message exists at all, a `console.error` is emitted and the chat renders empty (same behavior as before, but without the infinite reactive loop). ## How to reproduce 1. Start a chat and wait for a full LLM response + follow-up generation to begin. 2. While follow-ups are streaming, close the browser tab or kill the network. 3. Reopen the chat → infinite spinner. Or, inject an orphan manually into the DB (see issue #15189 for a ready-made JSON import that reliably triggers it). ## Testing - Tested with Playwright against a locally-built Docker image. - Baseline image (`v0.8.3-baseline`, unmodified): chat spins forever. - Fixed image (`v0.8.3-resilient`, this patch): chat loads, browser console shows the `console.warn` fallback message, zero errors. - Verified that normal (non-corrupted) chats are completely unaffected — the guard code is never triggered. ## Scope Single file changed: `src/lib/components/chat/Messages.svelte` (+34 / -10 lines). No backend changes, no new dependencies. --- <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-30 01:33:23 -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#49229