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

  1. Check out.code in practice: target value_interface vs value_verification_failed and treat accordingly.
  2. Only call set_value on elements that truly expose the AT-SPI Value interface (sliders, spinners); type into text fields instead.
  3. Clamp the requested value to the element's minValue/maxValue before writing.
  4. 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

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


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)