Summary
WebChat UI loses all state on browser refresh (F5): pending message queue, conversation history, and draft text in the input box. This was previously reported in #8331 but auto-closed as stale without a fix. Still reproducible in 2026.3.13.
Environment
- OpenClaw version: 2026.3.13 (61d171a)
- OS: Windows 11 (24H2)
- Channel: webchat
- Browser: Chrome (latest)
Steps to Reproduce
- Open WebChat UI at
http://127.0.0.1:18789/
- Send a message that triggers a long-running operation (e.g. subagent spawn via
sessions_spawn + sessions_yield)
- While the agent is processing, type and send 2-3 additional messages → they queue with "X pending" indicator
- Press F5 (or close and reopen the tab)
Expected Behavior
- Queued messages should persist and be submitted when the agent finishes
- Conversation history should be restored from the gateway session transcript
- Any unsent draft text in the input box should be preserved
Actual Behavior
- Queued messages are lost — user must retype them
- Conversation history is gone — blank screen
- Draft text is gone
Root Cause
All three forms of state exist only in React component state (memory). No persistence layer. The gateway already stores the session transcript in .jsonl files, but WebChat does not query it on reconnect.
Proposed Fix (expanded from #8331)
1. Queue persistence (original #8331 scope)
- Store pending messages in
localStorage keyed by session ID
- Key format:
oc-webchat-queue-${sessionId}
- On reconnect, restore the queue and submit when agent is ready
- TTL: 24h — remove stale entries on load
2. Conversation history persistence
- On WebChat load/reconnect, query the gateway for recent turns from the active session transcript
- Render them in the chat area so the user sees conversation context
- This is the highest-impact improvement — users lose visual context of the entire conversation on any refresh
- The gateway already has this data; WebChat just doesn't fetch it
3. Draft persistence
- Store unsent input text in
sessionStorage (or localStorage) keyed by session ID
- Key format:
oc-webchat-draft-${sessionId}
- Standard UX pattern — most chat apps (Slack, Discord, Telegram Web) preserve drafts
4. Reconnect indicator
- Show a brief toast: "Reconnected — restored X messages" so the user knows state was recovered
Alternative Architecture Consideration
Instead of client-side queue persistence, consider a server-side queue: when WebChat sends a message while the agent is busy, the gateway could accept and queue it server-side. This would make the queue persistent across devices, tabs, and refreshes without any localStorage dependency.
Impact
This affects any user who:
- Accidentally refreshes during a long operation (subagent spawns can take 1-10 minutes)
- Has the browser auto-refresh (extensions, dev tools)
- Closes and reopens the tab
- Uses multiple tabs (each loses the other's context)
References
Summary
WebChat UI loses all state on browser refresh (F5): pending message queue, conversation history, and draft text in the input box. This was previously reported in #8331 but auto-closed as stale without a fix. Still reproducible in 2026.3.13.
Environment
Steps to Reproduce
http://127.0.0.1:18789/sessions_spawn+sessions_yield)Expected Behavior
Actual Behavior
Root Cause
All three forms of state exist only in React component state (memory). No persistence layer. The gateway already stores the session transcript in
.jsonlfiles, but WebChat does not query it on reconnect.Proposed Fix (expanded from #8331)
1. Queue persistence (original #8331 scope)
localStoragekeyed by session IDoc-webchat-queue-${sessionId}2. Conversation history persistence
3. Draft persistence
sessionStorage(orlocalStorage) keyed by session IDoc-webchat-draft-${sessionId}4. Reconnect indicator
Alternative Architecture Consideration
Instead of client-side queue persistence, consider a server-side queue: when WebChat sends a message while the agent is busy, the gateway could accept and queue it server-side. This would make the queue persistent across devices, tabs, and refreshes without any
localStoragedependency.Impact
This affects any user who:
References