Hmbown/CodeWhale · warning · ExecError

select_text is not implemented on the win32 backend yet —…

Error message

select_text is not implemented on the win32 backend yet — fail-closed

What it means

The win32 backend has not implemented select_text; the method deliberately throws this fail-closed ExecError so callers never silently get a no-op. It is a capability gap of the backend, not a runtime fault — the request was valid but the feature does not exist on this platform yet.

Solutions

  1. Use an alternative on win32: shift+arrow keyboard sequences or double-click to select a word, then perform_action/copy.
  2. Gate the caller on backend capability — skip select_text when running on the win32 backend.
  3. Implement the method in win32.mjs using UIA TextPattern if your project needs it, replacing the fail-closed stub.

Example fix

// before
await backend.select_text({ target, start, end });
// after
if (typeof backend.select_text === 'function' && !backend.selectTextNotImplemented) {
  await backend.select_text({ target, start, end });
} else {
  await backend.key({ keys: ['shift', 'end'] }); // keyboard-based selection
}
Defensive patterns

Strategy: type-guard

Type guard

const supportsSelectText = (backend) =>
  backend && backend.backendId !== 'win32' && typeof backend.select_text === 'function';

Try / catch

if (supportsSelectText(backend)) {
  await backend.select_text({ target, start, end });
} else {
  await backend.key({ keys: ['shift', 'end'] }); // keyboard selection
}

Prevention

When it happens

Trigger: Any call to backend.select_text({...}) on the win32 backend, regardless of arguments. Always and immediately thrown.

Common situations: Agents attempting text selection workflows (select then copy) on Windows after they worked on a backend that supports it; generic tool scripts dispatching actions across backends without checking per-backend capability.

Related errors


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

Appendix: source

Thrown at crates/tui/plugins/computer-use/src/backends/win32.mjs:547

Start-Sleep -Milliseconds ${Math.round(d * 1000)};
${[...keys].reverse().map((code) => event(code, 2)).join("\n")}
Write-Output '{"ok": true}';`, { timeoutMs: Math.max(10_000, d * 1000 + 8000) });
        return { action_sent: true, key, heldSec: d };
      });
    },
    set_value: async ({ target, value }) => {
      const resolve = elementScript(target);
      const b64 = Buffer.from(String(value ?? ""), "utf16le").toString("base64");
      const j = await psJson(`${resolve}
$val = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('${b64}'));
$vp = $cur.GetCurrentPattern([System.Windows.Automation.ValuePattern]::Pattern);
if ($vp.Current.IsReadOnly) { throw 'element_read_only' }
$vp.SetValue($val);
@{ ok = $true; verified = ($vp.Current.Value -ceq $val) } | ConvertTo-Json -Compress;`, { timeoutMs: 45_000 });
      if (!j.ok) throw new ExecError("set_value failed");
      return { action_sent: true, strategy: "a11y", verified: j.verified === true };
    },
    select_text: async () => { throw new ExecError("select_text is not implemented on the win32 backend yet — fail-closed"); },
    perform_action: async ({ target, action = "Invoke" }) => {
      const resolve = elementScript(target);
      const actions = { invoke: ["Invoke", "Invoke"], click: ["Invoke", "Invoke"], toggle: ["Toggle", "Toggle"], expand: ["ExpandCollapse", "Expand"], expandcollapse: ["ExpandCollapse", "Expand"], collapse: ["ExpandCollapse", "Collapse"], select: ["SelectionItem", "Select"], selectionitem: ["SelectionItem", "Select"] };
      const chosen = actions[String(action).toLowerCase()];
      if (!chosen) throw new ExecError("unsupported UIA action");
      await psOk(`${resolve}
$pattern = $cur.GetCurrentPattern([System.Windows.Automation.${chosen[0]}Pattern]::Pattern);
$pattern.${chosen[1]}();`, { timeoutMs: 45_000 });
      return { action_sent: true, strategy: "a11y", action };
    },
    read_clipboard: async () => {
      const j = await psJson(`$t = Get-Clipboard -Raw -ErrorAction SilentlyContinue;
@{ text = [string]$t } | ConvertTo-Json -Compress;`, { timeoutMs: 10_000 });
      return { text: j.text ?? "", encoding: "utf8" };
    },
    write_clipboard: async ({ text }) => {
      const b64 = Buffer.from(String(text ?? ""), "utf16le").toString("base64");
      await psOk(`Set-Clipboard -Value ([System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('${b64}')));

View on GitHub (pinned to 73e0f67d83)