Plan approval popup: pressing Space while typing auto-confirms and dismisses without undo

Status Fixed / completed
Maintainer reply None cached
Activity 4 comments · opened May 26, 2026 · closed May 28, 2026

Summary

When the plan approval modal/popup appears mid-session, pressing the Space (or possibly Enter) key while the user is already composing a follow-up message is treated as confirming the plan. There is no undo, and the in-progress text is discarded. To cancel the approval (if / when noticed) requires clearing the text box and clicking the "stop" square button. However changes may already have been made by this point. The partial text may be recovered by using the up arrow key in the text box then resuming editing before submitting as normal.

Steps to reproduce

  1. Be mid-conversation with an active plan in plan mode
  2. Start typing a follow-up message in the input box before the plan modal fully renders
  3. Press Space (or possibly Enter) as part of normal typing
  4. The modal interprets Space (or possibly Enter) as a confirmation keystroke and auto-approves the plan

Expected behaviour

  • Keyboard input that lands in the chat input box should NOT propagate to a modal confirmation
  • OR: plan approval should require an explicit click or number confirmation on the modal element itself, not a loose keypress

Impact

Plan proceeds when user intended to add further requirements first. Creates frustration and trust issues with the approval flow. May lead to user losing in-progress text, especially if they're unaware of up arrow to recall previous entries.

Environment

Platform: Linux, VS Code extension

View original on GitHub ↗

4 Comments

github-actions[bot] · 4 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/37820
  2. https://github.com/anthropics/claude-code/issues/33988
  3. https://github.com/anthropics/claude-code/issues/37955

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

AlexHeylin · 4 months ago

While all these appear to report the same issue, they're all closed as duplicates and at least one is stated as duplicate of an issue which is itself closed as "unplanned" without any apparent human interation.

https://github.com/anthropics/claude-code/issues/37820 closed as duplicate of https://github.com/anthropics/claude-code/issues/35337 which is closed as "not planned" without minimal human interaction and apparently closed due to inactivity.

https://github.com/anthropics/claude-code/issues/37955 closed as duplicate of https://github.com/anthropics/claude-code/issues/33988 which is closed as a duplicate of https://github.com/anthropics/claude-code/issues/28722 which is closed as "not planned" without any apparent human interaction.

AlexHeylin · 4 months ago

Root Cause Analysis + Proposed Fix

I've investigated the bundled webview source (webview/index.js in the installed VS Code extension) and identified the exact cause.

The bug

The permission request modal (used for plan approval, AskUserQuestion, tool approval, etc.) has a useEffect that auto-focuses the "Yes" button 500 ms after the modal renders:

useEffect(() => {
  const timer = setTimeout(async () => {
    flushSync(() => { /* clears loading animation */ });
    if (yesButtonRef.current && document.hasFocus()) {
      setFocusedIndex(0);
      context.safeFocus(yesButtonRef.current); // ← moves focus to "Yes" button
    }
  }, 500);
  return () => clearTimeout(timer);
}, [toolName, context]);

safeFocus has no guards — it just calls .focus() if the panel is visible:

safeFocus(element) {
  if (this.comms.connection.value?.isVisible.value) element.focus();
}

The race condition

  1. User is composing a message in the chat input (typing spaces, or about to press Enter to submit)
  2. Plan/approval modal appears → 500 ms timer starts
  3. Timer fires → focus moves to the "Yes" <button>, regardless of whether the user is still typing
  4. Standard browser behaviour: Space or Enter on a focused <button> fires onClick
  5. Plan is approved; user's in-progress text is discarded

The 500 ms delay was clearly intended to give the user time to notice the modal before keyboard shortcuts activate, but it doesn't check whether the user is still in a text input — so it steals focus mid-keystroke.

Minimal fix (4 lines)

In the setTimeout callback, add an active-input guard before calling safeFocus:

const activeEl = document.activeElement;
const isUserTyping =
  activeEl &&
  (activeEl.tagName === 'INPUT' ||
    activeEl.tagName === 'TEXTAREA' ||
    activeEl.contentEditable === 'true' ||
    activeEl.contentEditable === '');

if (yesButtonRef.current && document.hasFocus() && !isUserTyping) {
  setFocusedIndex(0);
  context.safeFocus(yesButtonRef.current);
}

This preserves the existing auto-focus behaviour when the user is not typing, and prevents focus theft when they are. The modal still appears visually; the user can still Tab or click into it to use keyboard shortcuts.

Secondary hardening (optional but recommended)

The keyboard shortcut handler that processes number keys (1 = Yes, 2 = No, etc.) and Enter could also check a "user deliberately entered the modal" flag — i.e. only activate shortcuts after the user has explicitly clicked or tabbed into the modal container, not just because auto-focus fired. This eliminates any residual in-flight keystroke race even with the above fix in place.

Scope

The same safeFocus call pattern is used for the AskUserQuestion modal and tool-approval modals, so the fix is needed wherever the auto-focus-on-mount pattern exists — issues #28722, #33988, #35337, #37820, and #37955 are all the same root cause.

Happy to clarify anything. The fix is small enough to land in a patch release.

github-actions[bot] · 2 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.