{"record":{"id":"caaa468adeaff692","repo":"Hmbown/CodeWhale","slug":"element-disabled","errorCode":null,"errorMessage":"element_disabled","messagePattern":"element_disabled","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/linux.mjs","lineNumber":696,"sourceCode":"      await probeSession();\n      const k = xdotoolKey(text);\n      const d = Math.max(0.05, Math.min(30, Number(duration) || 1));\n      if (session === \"x11\") {\n        throwIfAborted();\n        heldKeys.add(k);\n        try {\n          await xdotool([\"keydown\", k]);\n          await wait(d * 1000);\n        } finally { await releaseKey(k); }\n      } else await waylandKey(text, { holdMs: Math.round(d * 1000) });\n      return { action_sent: true, key: k, heldSec: d };\n    },\n    set_value: async ({ target, value }) => {\n      // Select a supported interface before sending input. A refused write or\n      // failed readback must never trigger a second, ambiguously applied edit.\n      const out = await atspiResolve(target, `    state = found.getState()\n    if not state.contains(pyatspi.STATE_ENABLED):\n        raise RuntimeError(\"element_disabled\")\n    try:\n        editor = found.queryEditableText()\n    except NotImplementedError:\n        editor = None\n    if editor is not None:\n        if not state.contains(pyatspi.STATE_EDITABLE):\n            raise RuntimeError(\"element_read_only\")\n        if not editor.setTextContents(extra):\n            raise RuntimeError(\"value_rejected\")\n        text = found.queryText()\n        after = text.getText(0, text.characterCount)\n        if after != extra:\n            raise RuntimeError(\"value_verification_failed\")\n    else:\n        import math\n        desired = float(extra)\n        if not math.isfinite(desired):\n            raise RuntimeError(\"invalid_value\")","sourceCodeStart":678,"sourceCodeEnd":714,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/linux.mjs#L678-L714","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Enable the element first via the UI (or perform the enabling action) and retry set_value","Re-resolve the target — the reference may be stale and point at a replaced widget","Choose a different, enabled target that carries the same value","Fall back to keyboard/mouse input strategies if the element cannot be enabled"],"exampleFix":"// before\nawait backend.set_value({ target: \"#save-btn\", value: \"x\" }) // element_disabled\n// after\nawait backend.perform_action({ target: \"#enable-toggle\", action: \"click\" });\nawait backend.set_value({ target: \"#save-btn\", value: \"x\" });","handlingStrategy":"try-catch","validationCode":"// before calling set_value, check the element's state\nconst state = await backend.get_state?.(target);\nif (state && !state.enabled) throw new Error(`target ${target} is disabled; enable it first`);","typeGuard":"const isEnabled = (s) => Array.isArray(s) ? s.includes(\"enabled\") : s?.enabled === true;","tryCatchPattern":"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; }","preventionTips":["Check element enabled state before automating writes","Re-resolve targets after UI transitions — references go stale","Prefer targets that are interactable in the current UI state"],"tags":["accessibility","atspi","linux","ui-automation"],"backgroundTag":"element-disabled","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}