{"record":{"id":"6377412ab661fb7b","repo":"Hmbown/CodeWhale","slug":"reply-error-message","errorCode":null,"errorMessage":"${reply.error.message}","messagePattern":"\\$\\{reply\\.error\\.message\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/app/background-check.mjs","lineNumber":41,"sourceCode":"  child.stdout.on(\"data\", chunk => {\n    buffer += chunk;\n    if (buffer.length > 16_384) { controller.abort(); return; }\n    let newline;\n    while ((newline = buffer.indexOf(\"\\n\")) >= 0) {\n      const line = buffer.slice(0, newline); buffer = buffer.slice(newline + 1);\n      try { const result = JSON.parse(line); latest = result; if (result.event === \"ready\") ready = true; if (result.event === \"applied\") applied = result; } catch { /* Cocoa diagnostics are not receipts. */ }\n    }\n  });\n  async function until(predicate) {\n    while (!predicate()) {\n      if (spawnError) throw spawnError;\n      if (controller.signal.aborted || child.exitCode !== null) throw new Error(\"The check was interrupted. You can run it again when ready.\");\n      await delay(40);\n    }\n  }\n  async function call(tool, args = {}) {\n    const reply = await handle({ tool, args }, { sessionId, signal: controller.signal, persistentInputOwner: true });\n    if (!reply.ok) throw new Error(reply.error.message);\n    return reply.data;\n  }\n  try {\n    await until(() => ready);\n    await call(\"open_application\", { pid: child.pid, activate: false });\n    const state = await call(\"get_app_state\");\n    if (demoDirectory) {\n      fs.mkdirSync(demoDirectory, { recursive: true });\n      // AX can register before WindowServer makes a new window capturable.\n      // Retry only this read, before sending any input, within the check limit.\n      while (true) {\n        try { await call(\"screenshot\", { app_ref: { pid: child.pid }, path: path.join(demoDirectory, \"01-ready.png\") }); break; }\n        catch (error) {\n          if (controller.signal.aborted || !error.message.includes(\"not capturable\")) throw error;\n          await delay(100, undefined, { signal: controller.signal });\n        }\n      }\n    }","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/app/background-check.mjs#L23-L59","documentation":"call() is the thin wrapper the background check uses around the app-handler's handle() for every tool invocation (open_application, get_app_state, type, screenshot, ...). When the handler replies with reply.ok === false, the reply's error message is rethrown verbatim. The real cause is whatever the underlying tool reported — permission denials, invalid targets, internal tool failures.","triggerScenarios":"Any call(tool, args) in runBackgroundCheck where handle({ tool, args }, { sessionId, signal, persistentInputOwner: true }) resolves with { ok: false, error: { message } }; the thrown Error's message equals that inner message.","commonSituations":"Accessibility or Screen Recording permissions revoked mid-run, a tool receiving stale AX coordinates, or the daemon backend returning an internal error during a step.","solutions":["Read the rethrown message — it is the underlying tool's own error — and fix the cause it names (usually a macOS permission or an invalid target).","Re-run the check after granting Accessibility/Screen Recording permissions; macOS only applies them to already-running processes after approval.","If the inner message indicates a tool bug, capture the sessionId and app logs and file an issue against the computer-use plugin."],"exampleFix":"// before\nawait runBackgroundCheck({ bundle }); // opaque propagation\n\n// after\ntry {\n  await runBackgroundCheck({ bundle });\n} catch (e) {\n  // e.message is the raw tool error, e.g. a TCC permission denial\n  console.error(\"Background check tool failure:\", e.message);\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await runBackgroundCheck({ bundle });\n} catch (e) {\n  // e.message is the underlying tool's own error — log it with context\n  console.error(`Background check failed at a tool call: ${e.message}`);\n  if (/permission|Accessibility|Screen Recording/i.test(e.message)) {\n    console.error(\"Grant the named macOS permission, restart the process, retry.\");\n  }\n  throw e;\n}","preventionTips":["Grant Accessibility and Screen Recording permissions before starting; TCC applies to new processes only.","Treat the propagated message as the real diagnostic — route it to logs verbatim.","Keep sessionId/app logs when reporting failures so the failing tool can be identified."],"tags":["tool-error","propagation","computer-use","ipc"],"backgroundTag":"api-error-response","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}