openclaw - 💡(How to fix) Fix Control UI: mc() history merge discards local messages when server returns empty [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#71878Fetched 2026-04-26 05:07:08
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
closed ×1commented ×1

The mc() message-merge function in the Control UI frontend discards locally-streamed messages when the server's chat.history response returns an empty array. This causes the first assistant response in a new session (or after /new) to vanish immediately after streaming completes.

This is a separate bug from the chatLoading skeleton flash fixed in #71844 / 1cce439. That fix prevents the skeleton from replacing visible messages during reloads. This bug is about the merge logic itself silently dropping messages.

Related: #71371, #71844

Root Cause

In the minified bundle (index-*.js), the mc() merge function reconciles server history (e) with local messages (t):

function mc(e, t) {
  if (e.length === 0 || t.length === 0) return e;
  // ... merge logic ...
}

The problem is the early return: if (e.length === 0 || t.length === 0) return e. When the server returns empty (e = []) but the client has locally-streamed messages (t = [greeting]), it returns [] — wiping out the local messages.

Fix Action

Fix / Workaround

We've applied this patch locally alongside the chatLoading fix from #71844 and confirmed it resolves the issue. The combination of both fixes eliminates all message-disappearance symptoms we've observed over months of debugging.

Code Example

function mc(e, t) {
  if (e.length === 0 || t.length === 0) return e;
  // ... merge logic ...
}

---

- if (e.length === 0 || t.length === 0) return e;
+ if (t.length === 0) return e;
+ if (e.length === 0) return t;
RAW_BUFFERClick to expand / collapse

Summary

The mc() message-merge function in the Control UI frontend discards locally-streamed messages when the server's chat.history response returns an empty array. This causes the first assistant response in a new session (or after /new) to vanish immediately after streaming completes.

This is a separate bug from the chatLoading skeleton flash fixed in #71844 / 1cce439. That fix prevents the skeleton from replacing visible messages during reloads. This bug is about the merge logic itself silently dropping messages.

Related: #71371, #71844

Reproduction

  • Environment: WSL2 (Linux 6.6.x-microsoft-standard-WSL2), gateway on loopback
  • Steps:
    1. Start a new session (or /new)
    2. Send a message — watch the assistant response stream in
    3. Response finalizes — message disappears
    4. Browser refresh recovers it
  • Key condition: The backend hasn't persisted the turn by the time chat.history fires, so the server returns []
  • VS Code extension: Not affected — only the Control UI web frontend
  • More likely on WSL2 due to added virtual-network latency widening the race window

Root cause

In the minified bundle (index-*.js), the mc() merge function reconciles server history (e) with local messages (t):

function mc(e, t) {
  if (e.length === 0 || t.length === 0) return e;
  // ... merge logic ...
}

The problem is the early return: if (e.length === 0 || t.length === 0) return e. When the server returns empty (e = []) but the client has locally-streamed messages (t = [greeting]), it returns [] — wiping out the local messages.

Race sequence

  1. /new → session key changes → yc(e) starts (generation N)
  2. Assistant greeting streams → finalizes → push handler adds it to chatMessages
  3. Turn completion calls yc(e) again (generation N+1)
  4. yc() N+1: chat.history returns [] (backend hasn't committed yet)
  5. mc([], [greeting])e.length === 0 → returns []greeting wiped
  6. User sees empty chat until browser refresh

Suggested fix

Split the early-return condition so that empty server history preserves local messages:

- if (e.length === 0 || t.length === 0) return e;
+ if (t.length === 0) return e;
+ if (e.length === 0) return t;

This way:

  • Server empty + local messages → keep local messages (fixes the bug)
  • Server has data + local empty → keep server data (unchanged behavior)
  • Both empty → returns empty (unchanged)

We've applied this patch locally alongside the chatLoading fix from #71844 and confirmed it resolves the issue. The combination of both fixes eliminates all message-disappearance symptoms we've observed over months of debugging.

Environment

OpenClaw versions testedv2026.4.12 through v2026.4.24
OSWSL2 on Windows (Linux 6.6.87.2-microsoft-standard-WSL2)
Gatewayloopback-only, systemd user service
TriggerNew session or /new with first response

extent analysis

TL;DR

Update the mc() function to preserve local messages when the server returns an empty history array.

Guidance

  • Review the mc() function and verify that the early-return condition is causing the issue by checking if the server's chat.history response returns an empty array.
  • Apply the suggested fix by splitting the early-return condition to preserve local messages when the server history is empty.
  • Test the updated mc() function with different scenarios, including an empty server history and local messages, to ensure the fix resolves the issue.
  • Consider testing the fix in different environments, such as the VS Code extension, to ensure it doesn't introduce any regressions.

Example

function mc(e, t) {
  if (t.length === 0) return e;
  if (e.length === 0) return t;
  // ... merge logic ...
}

Notes

The suggested fix assumes that the mc() function is the root cause of the issue. However, it's essential to verify this by testing the updated function in different scenarios.

Recommendation

Apply the workaround by updating the mc() function to preserve local messages when the server returns an empty history array, as this fix has been confirmed to resolve the issue in local testing.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING