openclaw - ✅(Solved) Fix [Bug] Webchat: Enter key sends duplicate messages when pressed rapidly [1 pull requests, 1 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#72157Fetched 2026-04-27 05:34:00
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Participants
Timeline (top)
cross-referenced ×1

Root Cause

In the compiled JS file dist/control-ui/assets/index-*.js, the Enter key handler (around line 1537) checks connected status but misses checking sending state:

// Current code (buggy)
let t = e.connected;  // t = connected status
// ... later in keydown handler:
if(n.key === `Enter` && !n.shiftKey) {
  if(n.isComposing || n.keyCode === 229 || !e.connected) return;  // ❌ missing sending check
  n.preventDefault();
  t && (e.draft.trim() && f.push(e.draft), e.onSend());  // ❌ t is connected, not sending
}

The variable n (which holds sending status at declaration) gets shadowed by the event parameter n in the keydown callback, causing the sending check to be lost.

Note: The send button correctly disables with ?disabled=${!e.connected||e.sending}, but Enter key bypasses this safeguard.

Fix Action

Fix

Add sending and stream checks to the Enter key guard:

if(n.isComposing || n.keyCode === 229 || !e.connected || e.sending || e.stream !== null) return;

Temporary Workaround

I applied a local fix to the compiled JS file, but this will be overwritten on next openclaw update.


Thanks for maintaining OpenClaw! 🍡

PR fix notes

PR #72512: fix(webchat): guard Enter-to-send when a request is already in flight (#72157)

Description (problem / solution / changelog)

Closes #72157.

Problem

In webchat, pressing Enter rapidly (twice in quick succession) before the parent re-renders sends the message twice, producing duplicate backend requests.

Root cause

The send button is correctly guarded by `?disabled=${!props.connected || props.sending || props.stream !== null}`, surfacing as the in-scope helper:

// ui/src/ui/views/chat.ts:699
const isBusy = props.sending || props.stream !== null;

But the Enter-key path in `handleKeyDown` only checks `props.connected`:

// ui/src/ui/views/chat.ts:986-1001 (before fix)
if (e.key === \"Enter\" && !e.shiftKey) {
  if (e.isComposing || e.keyCode === 229) return;
  if (!props.connected) return;
  e.preventDefault();
  if (canCompose) {
    if (props.draft.trim()) inputHistory.push(props.draft);
    props.onSend();
  }
}

A fast double-Enter lands the second keystroke before the parent re-renders with `sending=true`, so the keyboard path bypasses the visual disable on the button. The reporter (#72157) traced this in the compiled bundle and gave the exact fix: also check `sending` and `stream`.

Reproducer

  1. Open webchat.
  2. Type a short message.
  3. Hit Enter twice in rapid succession (well under one render frame).
  4. Observe two identical requests to the backend.

Fix

Mirror the button's contract in the keyboard path by short-circuiting on the same `isBusy` that already exists in the closure:

if (isBusy) return;

Crucially, without `preventDefault` so the textarea remains usable (the user can still type / newline-edit while a request is in flight; we just don't fire a duplicate `onSend`).

Diff: +7 lines in `chat.ts`. No refactor.

Verification

pnpm vitest run ui/src/ui/views/chat.test.ts
# 34 passed (29 original + 5 new)

pnpm check
# 0 errors, 0 warnings; all policy guards green

Tests added (5 new, jsdom-based)

  1. Idle Enter happy path — single Enter on idle state calls `onSend` exactly once.
  2. `sending=true` — Enter is suppressed; `defaultPrevented === false` so the textarea stays interactive.
  3. Stream in flight (`stream !== null`) — Enter is suppressed.
  4. Disconnected — Enter is suppressed (existing behavior, regression-pinned).
  5. The exact #72157 repro: render with `sending=false` → press Enter (1 call) → re-render with `sending=true` (parent flipped state) → press Enter again → still only one `onSend` call. This is the actual bug pattern.

Compatibility

Pure additive guard. No API change. `onSend` signature unchanged. The 29 pre-existing chat.test.ts tests stay green.

Changed files

  • ui/src/ui/views/chat.test.ts (modified, +173/-0)
  • ui/src/ui/views/chat.ts (modified, +7/-0)

Code Example

// Current code (buggy)
let t = e.connected;  // t = connected status
// ... later in keydown handler:
if(n.key === `Enter` && !n.shiftKey) {
  if(n.isComposing || n.keyCode === 229 || !e.connected) return;  // ❌ missing sending check
  n.preventDefault();
  t && (e.draft.trim() && f.push(e.draft), e.onSend());  // ❌ t is connected, not sending
}

---

if(n.isComposing || n.keyCode === 229 || !e.connected || e.sending || e.stream !== null) return;
RAW_BUFFERClick to expand / collapse

Problem

When user presses Enter key rapidly (twice in quick succession) in webchat, the message is sent twice, causing duplicate requests to the backend.

Root Cause

In the compiled JS file dist/control-ui/assets/index-*.js, the Enter key handler (around line 1537) checks connected status but misses checking sending state:

// Current code (buggy)
let t = e.connected;  // t = connected status
// ... later in keydown handler:
if(n.key === `Enter` && !n.shiftKey) {
  if(n.isComposing || n.keyCode === 229 || !e.connected) return;  // ❌ missing sending check
  n.preventDefault();
  t && (e.draft.trim() && f.push(e.draft), e.onSend());  // ❌ t is connected, not sending
}

The variable n (which holds sending status at declaration) gets shadowed by the event parameter n in the keydown callback, causing the sending check to be lost.

Note: The send button correctly disables with ?disabled=${!e.connected||e.sending}, but Enter key bypasses this safeguard.

Fix

Add sending and stream checks to the Enter key guard:

if(n.isComposing || n.keyCode === 229 || !e.connected || e.sending || e.stream !== null) return;

Environment

  • OpenClaw version: 2026.4.24
  • Channel: webchat
  • Browser: Any

Impact

  • Causes duplicate backend requests
  • Can trigger duplicate cron job executions
  • Increases token usage unnecessarily

Reproduction

  1. Open webchat
  2. Type a message
  3. Press Enter twice rapidly
  4. Observe two identical messages sent

Temporary Workaround

I applied a local fix to the compiled JS file, but this will be overwritten on next openclaw update.


Thanks for maintaining OpenClaw! 🍡

extent analysis

TL;DR

To fix the issue of duplicate messages being sent when the Enter key is pressed rapidly in webchat, add a check for the sending state in the Enter key handler.

Guidance

  • Identify the Enter key handler in the compiled JS file dist/control-ui/assets/index-*.js and modify it to include a check for the sending state.
  • Update the condition to if(n.isComposing || n.keyCode === 229 || !e.connected || e.sending || e.stream !== null) return; to prevent duplicate requests.
  • Verify the fix by reproducing the issue and checking that only one message is sent when the Enter key is pressed rapidly.
  • Consider applying the temporary workaround to the local compiled JS file until a permanent fix is available.

Example

// Updated code (fixed)
if(n.isComposing || n.keyCode === 229 || !e.connected || e.sending || e.stream !== null) return;
n.preventDefault();
e.draft.trim() && f.push(e.draft), e.onSend();

Notes

The provided fix assumes that the sending state is correctly updated when a message is being sent. If this is not the case, additional modifications may be necessary.

Recommendation

Apply the workaround by updating the Enter key handler with the suggested condition, as this will prevent duplicate requests until a permanent fix is available.

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

openclaw - ✅(Solved) Fix [Bug] Webchat: Enter key sends duplicate messages when pressed rapidly [1 pull requests, 1 participants]