{"record":{"id":"b444283029feec1e","repo":"Hmbown/CodeWhale","slug":"timeout-after-opts-timeoutms-20-000-ms-cmd","errorCode":null,"errorMessage":"timeout after ${opts.timeoutMs ?? 20_000}ms: ${cmd}","messagePattern":"timeout after (.+?)ms: (.+?)","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/exec.mjs","lineNumber":156,"sourceCode":"          signal?.addEventListener(\"abort\", abort, { once: true });\n        });\n        child.stdin.write(JSON.stringify(message) + \"\\n\");\n        return await Promise.race([next, cancelled, new Promise((_, reject) => { commandTimer = setTimeout(() => reject(new ExecError(\"Native input owner did not acknowledge pointer motion\")), opts.timeoutMs ?? 20_000); })]);\n      }\n      catch (error) { await release().catch(() => {}); throw error; }\n      finally { clearTimeout(commandTimer); signal?.removeEventListener(\"abort\", abort); }\n    } };\n  } catch (error) {\n    await release().catch(() => {});\n    throw error;\n  } finally { clearTimeout(timer); }\n}\n\n/** run() and throw a typed error on non-zero exit / timeout. */\nexport async function runOk(cmd, args = [], opts = {}) {\n  const r = await run(cmd, args, opts);\n  if (r.aborted) throw Object.assign(new ExecError(\"computer request cancelled\", r), { code: \"cancelled\" });\n  if (r.timedOut) throw new ExecError(`timeout after ${opts.timeoutMs ?? 20_000}ms: ${cmd}`, r);\n  if (r.code !== 0) throw new ExecError(`${cmd} exited ${r.code}: ${trim(r.stderr || r.stdout)}`, r);\n  return r;\n}\n\nexport class ExecError extends Error {\n  constructor(message, result) {\n    super(message);\n    this.name = \"ExecError\";\n    this.result = result;\n  }\n}\n\n/** True when the executable exists on PATH (or opts.fullPath exists). */\nexport async function have(cmd) {\n  const probe = process.platform === \"win32\" ? \"where\" : \"which\";\n  const r = await run(probe, [cmd], { timeoutMs: 5000 });\n  return r.code === 0 && r.stdout.trim().length > 0;\n}","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/exec.mjs#L138-L174","documentation":"runOk wraps run() and converts timeouts into this typed ExecError, embedding the timeout duration and the command. The child process did not exit within opts.timeoutMs (default 20000ms), so run() killed it and flagged timedOut. This is a wall-clock deadline failure, not a non-zero exit code.","triggerScenarios":"Any runOk call whose command exceeds opts.timeoutMs: PowerShell UIA scripts on slow/loaded machines, hung target applications blocking an automation query, a stuck screenshot or input injection, or too small an explicit timeoutMs for a legitimately slow command.","commonSituations":"Under-provisioned CI machines where 20s PowerShell startup plus automation exceeds the budget; an unresponsive app whose UIA provider blocks; network-mapped paths stalling file operations; callers passing timeoutMs tuned for fast commands to slow ones.","solutions":["Increase opts.timeoutMs for the specific slow command (e.g. pass { timeoutMs: 60_000 } for UIA-heavy actions).","Check the target machine/app health — an unresponsive or modal-blocked app will hang any automation call.","Reduce work per call: split large scripts, or avoid operations known to block (modal dialogs, network paths).","Add retry with a longer budget if the slowness is transient (system under load)."],"exampleFix":"// before\nawait runOk('powershell', ['-NoProfile', '-Command', bigScript]);\n// after\nawait runOk('powershell', ['-NoProfile', '-Command', bigScript], { timeoutMs: 60_000 });","handlingStrategy":"retry","validationCode":null,"typeGuard":"const isTimeoutError = (e) =>\n  e instanceof Error && /^timeout after \\d+ms:/.test(e.message);","tryCatchPattern":"try {\n  return await runOk(cmd, args, { timeoutMs: budgetMs });\n} catch (e) {\n  if (isTimeoutError(e) && attempt < 2) return runWithRetry(cmd, args, budgetMs * 2, attempt + 1);\n  throw e;\n}","preventionTips":["Budget timeouts per command class (UIA-heavy actions need far more than 20s).","Detect and handle modal dialogs or hung apps that block automation indefinitely.","Avoid file operations on slow network paths inside timed scripts.","Add an exponential-backoff retry wrapper around runOk for known-slow commands."],"tags":["timeout","process","powershell"],"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"}