Hmbown/CodeWhale · error · RuntimeError

element_disabled

Error message

element_disabled

What it means

The linux computer-use backend's set_value uses an AT-SPI (pyatspi) script to write values into UI controls. Before writing, it reads the target's state set and refuses the edit with RuntimeError("element_disabled") when STATE_ENABLED is absent. This fail-closed check exists so a refused or ambiguous edit is never applied twice or partially.

Solutions

  1. Enable the element first via the UI (or perform the enabling action) and retry set_value
  2. Re-resolve the target — the reference may be stale and point at a replaced widget
  3. Choose a different, enabled target that carries the same value
  4. Fall back to keyboard/mouse input strategies if the element cannot be enabled

Example fix

// before
await backend.set_value({ target: "#save-btn", value: "x" }) // element_disabled
// after
await backend.perform_action({ target: "#enable-toggle", action: "click" });
await backend.set_value({ target: "#save-btn", value: "x" });
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling set_value, check the element's state
const state = await backend.get_state?.(target);
if (state && !state.enabled) throw new Error(`target ${target} is disabled; enable it first`);

Type guard

const isEnabled = (s) => Array.isArray(s) ? s.includes("enabled") : s?.enabled === true;

Try / catch

try { await backend.set_value({ target, value }); } catch (e) { if (String(e).includes("element_disabled")) { await enableTarget(target); return backend.set_value({ target, value }); } throw e; }

Prevention

When it happens

Trigger: Calling set_value({target, value}) on a UI element whose AT-SPI state does not contain STATE_ENABLED — a greyed-out menu item, a disabled button/input, or a stale target reference to a widget that was disabled after resolution.

Common situations: Trying to type into a form field that is disabled until another field is filled; automating a wizard step whose Next control is disabled due to validation; targeting an element in an inactive tab or unfocused window.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/caaa468adeaff692. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/plugins/computer-use/src/backends/linux.mjs:696

      await probeSession();
      const k = xdotoolKey(text);
      const d = Math.max(0.05, Math.min(30, Number(duration) || 1));
      if (session === "x11") {
        throwIfAborted();
        heldKeys.add(k);
        try {
          await xdotool(["keydown", k]);
          await wait(d * 1000);
        } finally { await releaseKey(k); }
      } else await waylandKey(text, { holdMs: Math.round(d * 1000) });
      return { action_sent: true, key: k, heldSec: d };
    },
    set_value: async ({ target, value }) => {
      // Select a supported interface before sending input. A refused write or
      // failed readback must never trigger a second, ambiguously applied edit.
      const out = await atspiResolve(target, `    state = found.getState()
    if not state.contains(pyatspi.STATE_ENABLED):
        raise RuntimeError("element_disabled")
    try:
        editor = found.queryEditableText()
    except NotImplementedError:
        editor = None
    if editor is not None:
        if not state.contains(pyatspi.STATE_EDITABLE):
            raise RuntimeError("element_read_only")
        if not editor.setTextContents(extra):
            raise RuntimeError("value_rejected")
        text = found.queryText()
        after = text.getText(0, text.characterCount)
        if after != extra:
            raise RuntimeError("value_verification_failed")
    else:
        import math
        desired = float(extra)
        if not math.isfinite(desired):
            raise RuntimeError("invalid_value")

View on GitHub (pinned to 73e0f67d83)