Hmbown/CodeWhale · error · ExecError

powershell.exe exited

Error message

powershell.exe exited ${r.code}: ${(r.stderr || r.stdout).trim().slice(0, 300)}

What it means

psOk throws this when powershell.exe terminates with a nonzero exit code. The message includes the exit code and up to 300 chars of stderr (or stdout if stderr is empty), surfacing whatever the script wrote. It exists so script failures (parse errors, thrown .NET exceptions, missing cmdlets) reach the caller truthfully instead of being swallowed.

Solutions

  1. Read the stderr/stdout excerpt in the message — it contains the actual PowerShell error
  2. Re-run the failing script manually in powershell.exe to reproduce and see the full error
  3. Check execution policy (Set-ExecutionPolicy) and that required modules/assemblies (.NET, System.Drawing, UIAutomation) load on the host
  4. If a generated script broke, update the backend script template for the PowerShell version installed on the host
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await psOk(script);
} catch (e) {
  if (e instanceof ExecError && /exited \d+/.test(e.message)) {
    console.error("powershell error detail:", e.message);
  }
}

Prevention

When it happens

Trigger: Any `ps()` run in the win32 backend whose ChildProcess exit code is not 0 — e.g. a PowerShell syntax error in a generated script, `Add-Type` failing, a cmdlet throwing a terminating error, or the process being terminated externally with a nonzero status.

Common situations: Windows PowerShell 5.1 vs PowerShell 7 syntax differences in generated scripts; execution policy or Constrained Language Mode blocking Add-Type; non-English locales writing errors to stderr; antivirus killing spawned PowerShell processes.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/0bcd85b4134383b4. Report an issue: GitHub.

Appendix: source

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

      "This held-input gesture requires a connected Codewhale Computer Use desktop helper so a disconnected client cannot leave keys or buttons pressed. Start the helper and reconnect before retrying."
    ), { code: "input_owner_required" });
  }

  async function ps(script, o = {}) {
    throwIfAborted();
    const encoded = Buffer.from(script, "utf16le").toString("base64");
    return runner("powershell.exe", ["-NoProfile", "-NonInteractive", "-EncodedCommand", encoded], {
      timeoutMs: o.timeoutMs ?? 25_000,
      maxBuffer: 32 * 1024 * 1024,
    });
  }

  /** ps() but truthful: timeout, nonzero exit, and spawn failure all throw. */
  async function psOk(script, o = {}) {
    const r = await ps(script, o);
    if (r.aborted) throw Object.assign(new ExecError("computer request cancelled", r), { code: "cancelled" });
    if (r.timedOut) throw new ExecError(`powershell timed out after ${o.timeoutMs ?? 25_000}ms`, r);
    if (r.code !== 0) throw new ExecError(`powershell.exe exited ${r.code}: ${(r.stderr || r.stdout).trim().slice(0, 300)}`, r);
    return r;
  }

  async function psJson(script, o = {}) {
    const r = await psOk(script, o);
    const out = r.stdout.trim();
    const j = tryJson(out, null);
    if (!j) throw new ExecError(`powershell did not return JSON: ${(r.stderr || out).trim().slice(0, 300)}`, r);
    return j;
  }

  let lastRaster = null;
  const heldButtons = new Set();
  const heldKeys = new Set();

  async function releaseInput({ buttons = [...heldButtons], keys = [...heldKeys] } = {}) {
    buttons = buttons.filter((button) => heldButtons.has(button));
    keys = keys.filter((key) => heldKeys.has(key));

View on GitHub (pinned to 433685b202)