Hmbown/CodeWhale · error · ExecError
set_value failed
Error message
set_value failed: ${out.code} What it means
set_value sets a numeric value on an AT-SPI value element via an embedded python script that writes and re-reads the value for verification. The library throws this when the script reported ok=false with a code — e.g. the element does not expose a value interface, or the write did not stick (value_verification_failed).
Solutions
- Check out.code in practice: target value_interface vs value_verification_failed and treat accordingly.
- Only call set_value on elements that truly expose the AT-SPI Value interface (sliders, spinners); type into text fields instead.
- Clamp the requested value to the element's minValue/maxValue before writing.
- Refresh the element path via get_app_state and retry once — stale nodes commonly cause the failure.
Example fix
// before
await backend.set_value({ target, value: 500 }); // slider max is 100 -> verification failed
// after
const clamped = Math.min(100, Math.max(0, 500));
await backend.set_value({ target, value: clamped }); Defensive patterns
Strategy: try-catch
Validate before calling
const el = await findElement(state, targetPath);
if (!el.interfaces?.includes('Value')) throw new Error('element has no AT-SPI Value interface'); Try / catch
try {
return await backend.set_value({ target, value });
} catch (e) {
if (String(e.message).includes('set_value failed:')) {
const fresh = await backend.get_app_state({ app_ref });
return backend.set_value({ target: reResolve(fresh), value: clamp(value) });
}
throw e;
} Prevention
- Only use set_value on sliders/spinners, not text fields
- Clamp values to the element's documented min/max before writing
- Refresh element paths immediately before writes to avoid stale nodes
When it happens
Trigger: Target element has no queryValue interface (not a slider/spinbox/progress); the value is read-only or clamped by the app so the post-write readback differs (RuntimeError value_verification_failed); stale element path resolved to the wrong node; a11y exceptions inside the script bubbling to ok=false.
Common situations: Trying to set_value on plain text fields (use type/key instead); sliders whose min/max reject the requested value; Electron apps exposing value poorly; paths captured from an outdated get_app_state snapshot.
Related errors
- application not found or name is ambiguous in the AT-SPI…
- AT-SPI action failed
- AT-SPI resolve failed
- AT-SPI walk failed — is python3-pyatspi installed and the…
- element_disabled
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/faccaa116a8e1b22.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/src/backends/linux.mjs:721
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")
numeric = found.queryValue()
numeric.currentValue = desired
after = numeric.currentValue
if after != desired:
raise RuntimeError("value_verification_failed")
print(json.dumps({"ok": True, "after": after}))`, String(value));
if (!out.ok) throw new ExecError(`set_value failed: ${out.code}`);
return { action_sent: true, strategy: "a11y", verified: true, after: out.after };
},
select_text: async () => { throw new ExecError("select_text is not implemented on the linux backend — fail-closed"); },
perform_action: async ({ target, action }) => {
const body = ` a = found.queryAction()
names = [a.getName(i) for i in range(a.nActions)]
want = (extra or "click").lower()
match = next((n for n in names if n.lower() == want), None)
if match is None and want == "click":
match = next((n for n in names if n.lower() in ("click", "press", "activate")), None)
if match is None:
print(json.dumps({"ok": False, "code": "action_not_found: " + ",".join(names)}))
else:
a.doAction(names.index(match))
print(json.dumps({"ok": True, "sent": True}))`;
const out = await atspiResolve(target, body, String(action));
if (!out.ok) throw new ExecError(`perform_action failed: ${out.code}`);
return { action_sent: true, strategy: "a11y", action };View on GitHub (pinned to 73e0f67d83)