Hmbown/CodeWhale · error · ExecError
Start-Process failed
Error message
Start-Process failed: ${r.stderr.trim().slice(0, 200)} What it means
open_application runs PowerShell's Start-Process to launch the target and throws this ExecError (carrying the process result r) when PowerShell exits non-zero. The message includes up to 200 characters of PowerShell stderr, which names the real cause.
Solutions
- Read the embedded stderr slice in the message — it names the missing file or handler
- Verify the app is installed and resolvable by bare name (try the full app name as registered, e.g. "Mozilla Firefox")
- For URLs, confirm a default handler exists for the scheme (e.g. https opens in some browser)
- Catch the ExecError, inspect err's attached process result, and fall back to list_apps to discover valid app names
Example fix
// before
await openApplication({ name: "ffox" });
// after
await openApplication({ name: "firefox" }); // or verify via list_apps first Defensive patterns
Strategy: try-catch
Try / catch
try {
return await backend.open_application({ name });
} catch (e) {
if (String(e.message).startsWith("Start-Process failed")) {
// e carries the process result; log stderr slice from the message
const apps = await backend.list_apps();
throw new Error(`Could not launch "${name}". Installed candidates: ${apps.displays ?? JSON.stringify(apps).slice(0, 300)}`);
}
throw e;
} Prevention
- Read the stderr slice embedded in the message for the root cause
- Verify the app is installed and resolvable by its registered name
- Confirm URL schemes have default handlers before launching
- Retain the ExecError's attached process result for diagnostics
When it happens
Trigger: Launching a name that isn't an installed app or on PATH (Start-Process cannot find the file); launching a .exe path with spaces mishandled; missing app association for a URL scheme; PowerShell/profile or execution-policy problems.
Common situations: Typos in the executable name; app not installed on the target Windows machine; attempting to open a URL whose protocol handler is unregistered; running in restricted environments where Start-Process is blocked.
Related errors
- powershell.exe exited
- powershell timed out after
- exited
- powershell did not return JSON
- powershell.exe exited
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/25e6c3e5450299bc.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/src/backends/win32.mjs:354
},
open_application: async ({ name, bundle_id: bid, url: urlArg, activate } = {}) => {
const target = name ?? bid;
if (typeof target !== "string" || !/^[A-Za-z0-9][A-Za-z0-9 .:_-]*$/.test(target)) throw new ExecError("open_application needs a plain app or executable name");
let argumentsScript = "";
if (urlArg != null) {
if (typeof urlArg !== "string" || !URL.canParse(urlArg) || /[\0\r\n]/.test(urlArg)) throw new ExecError("open_application url must be an absolute URL");
// Start-Process joins ArgumentList into a Windows command line. Quote
// one argument there, and transport that string as data into PowerShell.
const quoted = '"' + urlArg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\+)$/g, '$1$1') + '"';
const encoded = Buffer.from(quoted, "utf16le").toString("base64");
argumentsScript = `$launchArg = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('${encoded}')); `;
}
// activate defaults to background on every platform: a minimized
// launch leaves the user's foreground window alone. Windows input is
// still shared-surface — this only controls the launch, not input.
const windowStyle = activate === true ? "" : " -WindowStyle Minimized";
const r = await psOk(`${argumentsScript}Start-Process -FilePath "${target}"${windowStyle}${urlArg != null ? " -ArgumentList $launchArg" : ""}; Write-Output '{"launched": true}'`, { timeoutMs: 20_000 });
if (r.code !== 0) throw new ExecError(`Start-Process failed: ${r.stderr.trim().slice(0, 200)}`, r);
return { launched: true, name: target, url: urlArg ?? null, activate: activate === true };
},
get_app_state: async (args = {}) => {
if (Object.hasOwn(args, "window_id")) throw unsupportedSelector("Windows get_app_state does not support window_id");
const { app_ref, detail } = args;
if (Object.hasOwn(args, "app_ref") && (!app_ref || typeof app_ref !== "object" || Array.isArray(app_ref)
|| Object.keys(app_ref).length !== 1 || !Object.hasOwn(app_ref, "name") || typeof app_ref.name !== "string" || !app_ref.name.trim())) {
throw unsupportedSelector("Windows get_app_state supports only app_ref: { name: exact window title }; PID, bundle_id and other references are unsupported");
}
const filter = Buffer.from(app_ref?.name ?? "", "utf16le").toString("base64");
const maxEls = detail === "full" ? 800 : 400;
const j = await psJson(`${UIA_PRELUDE}
$max = ${maxEls};
$filter = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('${filter}'));
$root = [System.Windows.Automation.AutomationElement]::RootElement;
$els = New-Object System.Collections.ArrayList;
$found = $false; $truncated = $false; $appName = $null;
$targets = @($root.FindAll([System.Windows.Automation.TreeScope]::Children, [System.Windows.Automation.Condition]::TrueCondition));View on GitHub (pinned to 73e0f67d83)