Skip to content

[Bug]: Control UI chat-session-picker buttons unresponsive due to blur/click race condition #87554

@ryan4559

Description

@ryan4559

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

All interactive buttons inside the chat-session-picker dropdown (switch session, load more, search submit, clear search) silently fail because the search input's @blur handler destroys the DOM between the blur and click events via a Lit microtask re-render.

Steps to reproduce

  1. Open the Control UI dashboard (tested with Chrome).
  2. Navigate to the Chat tab.
  3. Open the session picker dropdown (the session name button in the chat controls bar).
  4. The search input auto-focuses via cA().
  5. Click any session option button to switch sessions.
  6. Observe the picker options flash (briefly disappear and reappear) but the session does not switch.
  7. The same failure applies to the "Load more" button, the search submit button, and the clear search button inside the picker.

Expected behavior

Clicking a session option switches to that session. Clicking "Load more" loads additional sessions. Clicking search/clear performs the respective action.

Actual behavior

All buttons inside the picker are unresponsive. The picker options flash briefly but no action is performed. No error is shown in the console. The session key remains unchanged.

Root cause analysis:

The search input in OA() has @blur=${()=>void _A(e)}. When the search query is empty, _A() calls vA() which synchronously sets chatSessionPickerResult = null and calls requestUpdate().

Modern browsers execute microtasks between individual DOM event dispatches (per the HTML spec's "clean up after running script" algorithm). The event sequence is:

  1. mousedown on option button
  2. blur on search input → vA() sets chatSessionPickerResult = nullrequestUpdate() schedules Lit update
  3. Microtask checkpoint → Lit re-renders → CA() returns nullwA() produces [] → all option buttons removed from DOM
  4. click dispatched → target element no longer exists → handler never fires

The uA() (close picker) and n(e, r.key) (switch session) calls inside the @click handler are never reached.

Affected handlers:

  • Session option: @click=${()=>{uA(e),r.key!==e.sessionKey&&n(e,r.key)}}
  • Load more: @click=${()=>void xA(e)}
  • Search submit: @click=${()=>void _A(e)}
  • Clear search: @click=${()=>vA(e)}

OpenClaw version

2026.5.26

Operating system

Ubuntu 22.04.5, browser: Chrome

Install method

npm global

Model

N/A — this is a frontend-only UI bug, not model-dependent

Provider / routing chain

N/A — this is a frontend-only UI bug, not provider-dependent

Additional provider/model setup details

No response

Logs, screenshots, and evidence

No console errors are produced. The bug is a silent event-ordering failure.

Verified by reading the minified source (`dist/control-ui/assets/index-s15Q2hqZ.js`):
- `OA()` renders the picker dialog with the search input's `@blur` handler and option `@click` handlers.
- `vA()` nulls `chatSessionPickerResult` synchronously and calls `requestUpdate()`.
- `CA()` returns `null` when `chatSessionPickerResult` is null and picker is open, causing `wA()` to return an empty array.
- Lit's microtask-based update removes all option buttons from the DOM before the `click` event dispatches.

**Local workaround applied and confirmed working:** changing `@click` to `@mousedown` with `preventDefault()` on all four buttons inside the picker. `preventDefault()` on `mousedown` suppresses the browser's default focus-shift behavior, preventing the `blur` from firing.

File: `dist/control-ui/assets/index-*.js` (filename contains a content hash)


# Session option button
- @click=${()=>{uA(e),r.key!==e.sessionKey&&n(e,r.key)}}
+ @mousedown=${t=>{t.button===0&&(t.preventDefault(),uA(e),r.key!==e.sessionKey&&n(e,r.key))}}

# Load more button
- @click=${()=>void xA(e)}
+ @mousedown=${t=>{t.button===0&&(t.preventDefault(),xA(e))}}

# Search submit button
- @click=${()=>void _A(e)}
+ @mousedown=${t=>{t.button===0&&(t.preventDefault(),_A(e))}}

# Clear search button
- @click=${()=>vA(e)}
+ @mousedown=${t=>{t.button===0&&(t.preventDefault(),vA(e))}}

Impact and severity

Affected: All Control UI users of the chat tab session picker
Severity: High — session switching via the picker is completely broken; the primary UI affordance for changing sessions does not work
Frequency: 100% reproducible on every click when the search input has focus (which is always, since the picker auto-focuses it on open)
Consequence: Users cannot switch sessions, load more sessions, or use search/clear in the session picker dropdown

Additional information

The suggested fix (using @mousedown + preventDefault()) is minimal and preserves existing behavior for keyboard users (Enter/Space on a focused button still works). An alternative fix would be to not null chatSessionPickerResult in vA() when chatSessionPickerOpen is true, instead keeping the stale result as a visual placeholder until gA() resolves.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.bugSomething isn't workingbug:behaviorIncorrect behavior without a crashclawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions