stablyai/orca · error · RuntimeError

window_not_focused: keyboard input requires the target windo

Error message

window_not_focused: keyboard input requires the target window to be focused; restoreWindow was requested but the target window is still not focused; bring it forward manually or check desktop permissions

What it means

Raised by require_keyboard_focus (runtime.py:180-191) when operation.get('restoreWindow') was truthy, the window did not have the AT-SPI ACTIVE state, and a 500ms polling loop (10× 50ms checks) failed to observe the window become ACTIVE. restore_window was attempted (in run_operation line 1049-1051 before require_keyboard_focus) via grab_focus or xdotool windowactivate, but the compositor still did not grant active focus — synthetic keyboard input would go to the wrong window, so the bridge refuses rather than type into the wrong app.

Source

Thrown at native/computer-use-linux/runtime.py:191

        ["xdotool", "search", "--pid", str(pid), "windowactivate", "--sync"],
        check=False,
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
    )


def require_keyboard_focus(window, operation):
    if has_state(window, Atspi.StateType.ACTIVE):
        return
    if operation.get("restoreWindow"):
        deadline = time.monotonic() + 0.5
        while time.monotonic() < deadline:
            if has_state(window, Atspi.StateType.ACTIVE):
                return
            time.sleep(0.05)
        if has_state(window, Atspi.StateType.ACTIVE):
            return
        raise RuntimeError("window_not_focused: keyboard input requires the target window to be focused; restoreWindow was requested but the target window is still not focused; bring it forward manually or check desktop permissions")
    raise RuntimeError("window_not_focused: keyboard input requires the target window to be focused; retry with --restore-window")


def app_matches(app, query):
    needle = str(query or "").strip().lower()
    if not needle:
        return False
    if needle.startswith("pid:"):
        requested_pid = parse_positive_pid(needle[4:])
        return requested_pid is not None and pid_of(app) == requested_pid
    if needle.isdigit() and int(needle) > 0 and pid_of(app) == int(needle):
        return True
    haystacks = [name_of(app).lower()] + [name_of(window).lower() for _, window in windows_for(app)]
    return any(value == needle or needle in value for value in haystacks)


def parse_positive_pid(value):
    return int(value) if value.isdigit() and int(value) > 0 else None

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Manually bring the target window to the foreground (click it, Alt-Tab to it) and retry without restoreWindow.
  2. On Wayland, ensure the AT-SPI bridge and Orca have permission to grab focus (focus-stealing-prevention disabled or the right xdg-desktop-portal).
  3. Increase robustness by retrying the operation after a longer settle, or chain multiple restore attempts with xdotool.
  4. If the window is on another workspace, switch to that workspace first (wmctrl -s or xdotool set_desktop_for_window).
Defensive patterns

Strategy: fallback

Validate before calling

# Pre-check focus state before requiring keyboard focus
if not has_state(window, Atspi.StateType.ACTIVE) and not operation.get('restoreWindow'):
    operation['restoreWindow'] = True  # let the bridge attempt activation
# also pre-check the window is restorable (not on another workspace, etc.)

Type guard

def window_has_focus(window) -> bool:
    return has_state(window, Atspi.StateType.ACTIVE)

Try / catch

try:
    require_keyboard_focus(window, operation)
except RuntimeError as exc:
    if 'still not focused' in str(exc):
        # manual fallback: prompt user to bring window forward, or switch workspace
        raise SystemExit(f'Could not activate {name_of(window)}. Bring it forward manually and retry.')
    raise

Prevention

When it happens

Trigger: type_text/press_key/hotkey/paste_text called with restoreWindow:true on a window that another app's focus-stealing, a fullscreen/always-on-top window, minimized state, or lacking focus permissions prevents from becoming ACTIVE within 500ms. restore_window's grab_focus returned false or xdotool's windowactivate didn't take effect.

Common situations: GNOME/Mutter focus-stealing-prevention blocking grab_focus; a fullscreen game or always-on-top dialog keeping focus; the target window on a different virtual desktop; the user's session lacks permission to programmatically activate windows (Wayland without the right portal).

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/9f28b4f2c785d61b. Report an issue: GitHub.