eae3d57 fix: handle orphan messages in chat history to prevent UI deadlock
📊 Changes
1 file changed (+29 additions, -2 deletions)
View changed files
📝src/lib/components/chat/Messages.svelte (+29 -2)
📄 Description
Summary
Orphan messages (missing id, role, or parentId) in history.messages cause the UI to hang forever on a loading spinner when opening the chat
No errors in console, no crash — just a silent deadlock
The fix makes the frontend resilient to malformed chat data
Root Cause
Three issues in src/lib/components/chat/Messages.svelte:
Infinite spinner — The "load more" check messages.at(0)?.parentId !== null uses strict equality. Orphan messages with missing parentId (undefined) pass this check (undefined !== null is true), showing the loader forever.
Broken tree traversal — Same strict !== null check in buildMessages() when walking the parent chain.
Blank page — When currentId points to an orphan, buildMessages() can only reach the orphan (no parent chain to valid messages), rendering nothing useful.
Fix
Change
Line
Description
Loose null check in template
481
!== null → != null so undefined and null both mean "root message"
Loose null check in traversal
94
Same fix in buildMessages() parent chain walk
Fallback for invalid currentId
80-112
New findLastValidMessageId() — when currentId points to invalid message, scan for the latest valid one and switch to it
Steps to Reproduce (before fix)
Import a chat with a malformed message (orphan with no id/role/parentId in history.messages, and currentId pointing to it)
Click on the imported chat
Bug: UI shows loading spinner forever, chat is inaccessible
Test JSON for reproduction
[{"id":"8a3351f4-79c1-4731-8826-d5783944b0c2","user_id":"fe7bbdce-2468-4ce4-aa02-00edd8c48e76","title":"Malformed Chat Test","chat":{"id":"","title":"Malformed Chat Test","models":["llama3.2:1b"],"params":{},"history":{"messages":{"msg-1":{"id":"msg-1","parentId":null,"childrenIds":["msg-2"],"role":"user","content":"What is Python?","timestamp":1750304001},"msg-2":{"id":"msg-2","parentId":"msg-1","childrenIds":[],"role":"assistant","content":"Python is a programming language.","model":"llama3.2:1b","timestamp":1750304002,"done":true},"orphan-1":{"model":"llama3.2:1b","content":"Orphan message - no id, no role, no parentId"}},"currentId":"orphan-1"},"messages":[{"id":"msg-1","parentId":null,"childrenIds":["msg-2"],"role":"user","content":"What is Python?","timestamp":1750304001},{"id":"msg-2","parentId":"msg-1","childrenIds":[],"role":"assistant","content":"Python is a programming language.","model":"llama3.2:1b","timestamp":1750304002,"done":true}],"tags":[],"timestamp":1750304001000,"files":[]},"updated_at":1750307488,"created_at":1750304001,"share_id":null,"archived":false,"pinned":false,"meta":{},"folder_id":null}]
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/23455
**Author:** [@weyseing](https://github.com/weyseing)
**Created:** 4/6/2026
**Status:** 🔄 Open
**Base:** `dev` ← **Head:** `fix/orphan-message-deadlock`
---
### 📝 Commits (1)
- [`eae3d57`](https://github.com/open-webui/open-webui/commit/eae3d576bb9d82b623e7334a10fb1f389b70f4a6) fix: handle orphan messages in chat history to prevent UI deadlock
### 📊 Changes
**1 file changed** (+29 additions, -2 deletions)
<details>
<summary>View changed files</summary>
📝 `src/lib/components/chat/Messages.svelte` (+29 -2)
</details>
### 📄 Description
## Summary
- Orphan messages (missing `id`, `role`, or `parentId`) in `history.messages` cause the UI to hang forever on a loading spinner when opening the chat
- No errors in console, no crash — just a silent deadlock
- The fix makes the frontend resilient to malformed chat data
## Root Cause
Three issues in `src/lib/components/chat/Messages.svelte`:
1. **Infinite spinner** — The "load more" check `messages.at(0)?.parentId !== null` uses strict equality. Orphan messages with missing `parentId` (`undefined`) pass this check (`undefined !== null` is `true`), showing the loader forever.
2. **Broken tree traversal** — Same strict `!== null` check in `buildMessages()` when walking the parent chain.
3. **Blank page** — When `currentId` points to an orphan, `buildMessages()` can only reach the orphan (no parent chain to valid messages), rendering nothing useful.
## Fix
| Change | Line | Description |
|--------|------|-------------|
| Loose null check in template | 481 | `!== null` → `!= null` so `undefined` and `null` both mean "root message" |
| Loose null check in traversal | 94 | Same fix in `buildMessages()` parent chain walk |
| Fallback for invalid `currentId` | 80-112 | New `findLastValidMessageId()` — when `currentId` points to invalid message, scan for the latest valid one and switch to it |
## Steps to Reproduce (before fix)
1. Import a chat with a malformed message (orphan with no `id`/`role`/`parentId` in `history.messages`, and `currentId` pointing to it)
2. Click on the imported chat
3. **Bug:** UI shows loading spinner forever, chat is inaccessible
<details>
<summary>Test JSON for reproduction</summary>
```json
[
{
"id": "8a3351f4-79c1-4731-8826-d5783944b0c2",
"user_id": "fe7bbdce-2468-4ce4-aa02-00edd8c48e76",
"title": "Malformed Chat Test",
"chat": {
"id": "",
"title": "Malformed Chat Test",
"models": ["llama3.2:1b"],
"params": {},
"history": {
"messages": {
"msg-1": {
"id": "msg-1", "parentId": null, "childrenIds": ["msg-2"],
"role": "user", "content": "What is Python?", "timestamp": 1750304001
},
"msg-2": {
"id": "msg-2", "parentId": "msg-1", "childrenIds": [],
"role": "assistant", "content": "Python is a programming language.",
"model": "llama3.2:1b", "timestamp": 1750304002, "done": true
},
"orphan-1": {
"model": "llama3.2:1b",
"content": "Orphan message - no id, no role, no parentId"
}
},
"currentId": "orphan-1"
},
"messages": [
{ "id": "msg-1", "parentId": null, "childrenIds": ["msg-2"], "role": "user", "content": "What is Python?", "timestamp": 1750304001 },
{ "id": "msg-2", "parentId": "msg-1", "childrenIds": [], "role": "assistant", "content": "Python is a programming language.", "model": "llama3.2:1b", "timestamp": 1750304002, "done": true }
],
"tags": [], "timestamp": 1750304001000, "files": []
},
"updated_at": 1750307488, "created_at": 1750304001,
"share_id": null, "archived": false, "pinned": false, "meta": {}, "folder_id": null
}
]
```
</details>
## Testing
- Imported malformed chat with 3 orphan messages + 6 valid messages
- Before fix: infinite loading spinner, chat inaccessible
- After fix: orphans skipped, full conversation renders normally
- Verified normal chats still work correctly
- Tested with Ollama (llama3.2:1b) via Docker Compose on macOS
Fixes #15189
---
- [x] 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>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/open-webui/open-webui/pull/23455
Author: @weyseing
Created: 4/6/2026
Status: 🔄 Open
Base:
dev← Head:fix/orphan-message-deadlock📝 Commits (1)
eae3d57fix: handle orphan messages in chat history to prevent UI deadlock📊 Changes
1 file changed (+29 additions, -2 deletions)
View changed files
📝
src/lib/components/chat/Messages.svelte(+29 -2)📄 Description
Summary
id,role, orparentId) inhistory.messagescause the UI to hang forever on a loading spinner when opening the chatRoot Cause
Three issues in
src/lib/components/chat/Messages.svelte:Infinite spinner — The "load more" check
messages.at(0)?.parentId !== nulluses strict equality. Orphan messages with missingparentId(undefined) pass this check (undefined !== nullistrue), showing the loader forever.Broken tree traversal — Same strict
!== nullcheck inbuildMessages()when walking the parent chain.Blank page — When
currentIdpoints to an orphan,buildMessages()can only reach the orphan (no parent chain to valid messages), rendering nothing useful.Fix
!== null→!= nullsoundefinedandnullboth mean "root message"buildMessages()parent chain walkcurrentIdfindLastValidMessageId()— whencurrentIdpoints to invalid message, scan for the latest valid one and switch to itSteps to Reproduce (before fix)
id/role/parentIdinhistory.messages, andcurrentIdpointing to it)Test JSON for reproduction
Testing
Fixes #15189
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.