stablyai/orca · error · RuntimeError

No top-level AT-SPI window is available for {app}

Error message

No top-level AT-SPI window is available for {app}

What it means

Raised by choose_window (runtime.py:144-147) when windows_for(app) returns an empty list — the matched application exposes no top-level AT-SPI children classified as windows. windows_for keeps a child only if it has a screen rect OR its role is in {frame, window, dialog, alert}; an app with zero such children triggers this. The error names the app via name_of(app) so the caller knows which application lacks a usable window.

Source

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

    for _, app in children(desktop_root()):
        if name_of(app):
            yield app


def windows_for(app):
    result = []
    for index, child in children(app):
        role = role_of(child).lower()
        rect = screen_rect(child)
        if rect is not None or role in {"frame", "window", "dialog", "alert"}:
            result.append((index, child))
    return result


def choose_window(app, window_id=None, window_index=None):
    windows = windows_for(app)
    if not windows:
        raise RuntimeError("No top-level AT-SPI window is available for " + name_of(app))
    if window_id is not None:
        raise RuntimeError("windowId is not supported by the Linux AT-SPI provider; use windowIndex")
    if window_index is not None:
        for item in windows:
            if item[0] == int(window_index):
                return item
        raise RuntimeError(f'windowNotFound("{window_index}")')
    for item in windows:
        if has_state(item[1], Atspi.StateType.ACTIVE):
            return item
    for item in windows:
        if has_state(item[1], Atspi.StateType.SHOWING):
            return item
    return windows[0]


def restore_window(app, window=None):
    target = window if window is not None else app

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Restore the app's window from its tray/dock before calling (some apps respond to a second launch with --activate or dbus activation).
  2. Call list_apps first to confirm you matched the right process; use 'pid:<pid>' to disambiguate from helper processes.
  3. Retry after a short delay if the app was just launched and the window isn't registered yet.
  4. On flatpak/snap apps, ensure AT-SPI is accessible across the sandbox (x11 --socket, accessibility bus sharing).
Defensive patterns

Strategy: validation

Validate before calling

# Before choose_window, check the app has windows
windows = windows_for(app)
if not windows:
    raise SystemExit(f'App {name_of(app)} has no open windows. Restore one and retry.')

Type guard

def app_has_windows(app) -> bool:
    return bool(windows_for(app))

Try / catch

try:
    window = choose_window(app)
except RuntimeError as exc:
    if str(exc).startswith('No top-level AT-SPI window'):
        # restore from tray / activate, then retry once
        restore_window(app)
        time.sleep(0.3)
        window = choose_window(app)
    else:
        raise

Prevention

When it happens

Trigger: find_app matched an app (by name/pid) but the app has no visible windows: all windows closed (app is in system-tray-only/background state), windows are minimized to tray without an AT-SPI frame representation, the app exposes only menu-bar/menubar-role children, or the app is a background helper process that registered an AT-SPI app object without UI.

Common situations: Targeting a tray-only app (Discord, Slack, Dropbox) that was closed to tray; an app that just launched and hasn't created a window yet; a flatpak/snap app whose AT-SPI tree is sandboxed and reports no windows; a wrong app match (e.g., matched a helper process instead of the real app).

Related errors


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