{"record":{"id":"c9bf7792fe9bc43a","repo":"Hmbown/CodeWhale","slug":"powershell-timed-out-after-o-timeoutms-25-000-ms","errorCode":null,"errorMessage":"powershell timed out after ${o.timeoutMs ?? 25_000}ms","messagePattern":"powershell timed out after (.+?)ms","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/win32.mjs","lineNumber":182,"sourceCode":"    if (opts.exec?.persistentInputOwner !== true) throw Object.assign(new ExecError(\n      \"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.\"\n    ), { code: \"input_owner_required\" });\n  }\n\n  async function ps(script, o = {}) {\n    throwIfAborted();\n    const encoded = Buffer.from(`$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';\\n[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false);\\n${script}`, \"utf16le\").toString(\"base64\");\n    return runner(\"powershell.exe\", [\"-NoProfile\", \"-NonInteractive\", \"-EncodedCommand\", encoded], {\n      timeoutMs: o.timeoutMs ?? 25_000,\n      maxBuffer: 32 * 1024 * 1024,\n    });\n  }\n\n  /** ps() but truthful: timeout, nonzero exit, and spawn failure all throw. */\n  async function psOk(script, o = {}) {\n    const r = await ps(script, o);\n    if (r.aborted) throw Object.assign(new ExecError(\"computer request cancelled\", r), { code: \"cancelled\" });\n    if (r.timedOut) throw new ExecError(`powershell timed out after ${o.timeoutMs ?? 25_000}ms`, r);\n    if (r.code !== 0) {\n      const raw = (r.stderr || r.stdout).trim();\n      // EncodedCommand serializes errors as CLIXML; surface the error strings,\n      // not a truncated XML/progress header that conceals the actual failure.\n      const messages = [...raw.matchAll(/<S S=\"Error\">([\\s\\S]*?)<\\/S>/g)].map(m => m[1]\n        .replace(/_x([0-9A-Fa-f]{4})_/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))\n        .replace(/&lt;/g, \"<\").replace(/&gt;/g, \">\").replace(/&quot;/g, '\"').replace(/&apos;/g, \"'\").replace(/&amp;/g, \"&\"));\n      throw new ExecError(`powershell.exe exited ${r.code}: ${(messages.join(\"\") || raw).slice(0, 1600)}`, r);\n    }\n    return r;\n  }\n\n  async function psJson(script, o = {}) {\n    const r = await psOk(script, o);\n    const out = r.stdout.trim();\n    const j = tryJson(out, null);\n    if (!j) throw new ExecError(`powershell did not return JSON: ${(r.stderr || out).trim().slice(0, 300)}`, r);\n    return j;","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/win32.mjs#L164-L200","documentation":"psOk wraps every PowerShell invocation and is 'truthful': unlike ps(), it throws instead of returning results on timeout, nonzero exit, or spawn failure. When the spawned powershell.exe exceeds the caller's timeoutMs (default 25s), it throws this ExecError with the effective timeout value.","triggerScenarios":"Any computer-use operation backed by a PowerShell script (UIA queries, screenshots, window enumeration) exceeding its timeoutMs — e.g. slow UIA tree walks, hung COM automation, first-run .NET/PowerShell startup delays on cold machines, or an explicit small timeoutMs passed in options.","commonSituations":"25s default too short for large UIA trees or AV-scanned PowerShell startup; a custom timeoutMs set optimistically low; a hung PowerShell child waiting on a modal dialog.","solutions":["Increase timeoutMs in the options object for slow operations (e.g. { timeoutMs: 60000 })","Profile the script manually in powershell.exe to find the slow or blocking statement","Trim UIA queries to smaller scopes (single window/element) instead of whole-desktop tree walks","Retry once on timeout; also check for warm-up effects (first call after boot is much slower)"],"exampleFix":"// before\nawait psOk(uiaScript);\n// after\nawait psOk(uiaScript, { timeoutMs: 60_000 });","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"let last;\nfor (const t of [25_000, 60_000]) {\n  try { return await psOk(script, { timeoutMs: t }); }\n  catch (e) { if (!/timed out/.test(e.message)) throw e; last = e; }\n}\nthrow last;","preventionTips":["Budget generous timeouts for UIA-heavy scripts","Warm up PowerShell once at session start to pay JIT/profile costs early","Avoid modal dialogs that hang scripts mid-run","Scope UIA queries narrowly to keep runtime predictable"],"tags":["powershell","timeout","windows","automation","process"],"backgroundTag":"request-timeout","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}