Skip to content

get_app_state (and thus all tools) crash on Linux: 'Accessible' object has no attribute 'is_text' #51

Description

@dengjzy

Environment

  • OS: Ubuntu 24.04 (Linux 7.0.0-28-generic), GNOME on X11 (not Wayland)
  • Python: 3.12.3 (system), gi GObject Introspection with Atspi 2.0 (gi.repository.Atspi)
  • open-computer-use: v0.3.1 (npm, dist/linux/amd64/open-computer-use — a Go binary embedding apps/OpenComputerUseLinux/runtime.py)
  • Node: v18.19.1 (system)

Problem 1 (critical): every tool crashes with 'Accessible' object has no attribute 'is_text'

On this system, all tools that read the accessibility tree crash:

open-computer-use call get_app_state --args '{"app":"qqmusic"}'
>>> 'Accessible' object has no attribute 'is_text'

type_text crashes the same way with a sibling attribute:

open-computer-use call type_text --args '{"app":"qqmusic","text":"hi"}'
>>> 'Accessible' object has no attribute 'is_editable_text'

Because every action tool is gated behind app state ("No app state is available for X. Run get_app_state before action tools."), one AttributeError makes the entire server unusable on Linux.

Root cause

The embedded runtime.py treats is_text / is_editable_text as attributes of the Atspi.Accessible object:

  • runtime.py:220if not bool(safe(node.is_text, False)):
  • runtime.py:410if focused is None or not bool(safe(focused.is_text, False)):
  • runtime.py:693return bool(safe(node.is_editable_text, False)) and ...
  • runtime.py:720if node is not None and bool(safe(node.is_editable_text, False)):

In the gi bindings (gi.repository.Atspi), Atspi.Accessible has no is_text/is_editable_text attribute. Interface presence is queried via node.get_interfaces() (returns e.g. ['Accessible', 'Action', 'Collection', 'Component', 'Hyperlink', 'Text']). Because the attribute is evaluated eagerly at call time, the AttributeError fires before safe() can catch it — so safe(node.is_text, False) never protects anything.

Suggested fix

Replace the attribute accesses with interface checks:

def is_text_node(node):
    try:
        return "Text" in node.get_interfaces()
    except Exception:
        return False

def is_editable_text_node(node):
    try:
        return "EditableText" in node.get_interfaces()
    except Exception:
        return False

and use those in the four call sites above.

Workaround used

I worked around it locally (without touching the Go binary) by monkeypatching the missing properties onto Atspi.Accessible from a .pth-loaded Python module:

# ocu_fix.py (loaded via ocu_fix.pth in a site-packages dir)
import gi
gi.require_version("Atspi", "2.0")
from gi.repository import Atspi
if not hasattr(Atspi.Accessible, "is_text"):
    Atspi.Accessible.is_text = property(lambda self: "Text" in self.get_interfaces())
if not hasattr(Atspi.Accessible, "is_editable_text"):
    Atspi.Accessible.is_editable_text = property(lambda self: "EditableText" in self.get_interfaces())

Note: a sitecustomize.py in the user site-packages does not work — Ubuntu ships /usr/lib/python3.12/sitecustomize.py, and Python only loads the first sitecustomize on sys.path. The .pth import ocu_fix mechanism is what reliably runs.

Problem 2: type_text cannot type CJK on Chromium/Electron apps

type_text first tries insert_text(), which requires the target node to expose the EditableText interface. On Chromium/Electron apps the search <input> is exposed with Text but no EditableText, so insert_text returns False and it falls back to send_text() (Atspi.generate_keyboard_event(..., KeySynthType.STRING)), which synthesizes keysyms and cannot produce CJK characters. On Chinese-language apps, type_text therefore cannot enter text; the only reliable route is pasting from the X clipboard into a focused field.

This would be worth documenting (or handling) if CJK input is expected to work.

Problem 3: Chromium/Electron apps expose an empty web-content tree to AT-SPI

Against QQ Music (an Electron app), get_app_state returns only empty document web nodes until the app is launched with --force-renderer-accessibility. Without that flag, no widgets (search box, buttons, song rows) are exposed at all, so element-indexed click/type_text cannot target anything. Worth a note in the README for Electron/Chromium targets.


Happy to provide more logs or test a patch if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions