Skip to content

Control UI webchat: duplicate assistant messages rendered on every reply #5964

Description

@astoreyai

Description

Every assistant reply in the Control UI webchat (port 18789) appears twice in the chat view. This happens consistently on every message, not intermittently.

Environment

  • OpenClaw version: 2026.1.30
  • Browser: Chromium-based (tested on multiple)
  • OS: Debian Linux (x64)
  • Gateway mode: local, LAN bind

Steps to reproduce

  1. Open the Control UI webchat at http://<gateway-ip>:18789/chat
  2. Send any message
  3. Observe the assistant reply appears twice

Analysis

I traced through the minified client JS (index-CXUONUC9.js) and the server-side server-chat.js. The server transcript (.jsonl) contains no duplicates — each assistant message appears exactly once. This is purely a client-side rendering issue.

Likely cause

When a chat event with state: 'final' arrives:

  1. chatStream is set to null (clearing the streaming entry)
  2. St(e) (chat.history fetch) is called asynchronously
  3. The history response replaces chatMessages entirely

The duplicate likely occurs because:

  • The final chat event's message payload may be rendered as a new entry before chatStream is fully cleared in the same render cycle
  • OR chat.history is being triggered from multiple paths (e.g., both the final event handler AND a tab re-focus / reconnect handler)

Key code paths (from minified source)

  • zl() — handles chat event state transitions (delta/final/error)
  • St() — fetches chat.history and replaces chatMessages
  • vg() — gateway event dispatcher, calls St(e) on state === 'final'
  • ei() — tab init, also calls Zo()St() for chat tab

Expected behavior

Each assistant message should appear exactly once.

Workaround

Refreshing the page shows correct history (no duplicates), confirming it's a live rendering issue only.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstaleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions