{"record":{"id":"1c9c5810777785ea","repo":"ComposioHQ/composio","slug":"local-command-failed-for-context-finalslug-i","errorCode":null,"errorMessage":"Local command failed for ${context.finalSlug}: ${invocation.command} ${(invocation.args ?? []).join(' ')}\nexitCode=${exitCode ?? 'null'} signal=${signal ?? 'null'}\nstderr: ${stderr.trim()}","messagePattern":"Local command failed for (.+?): (.+?) (.+?)\nexitCode=(.+?) signal=(.+?)\nstderr: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ts/packages/cli-local-tools/src/runtime.ts","lineNumber":142,"sourceCode":"    child.stdin.end(invocation.stdin);\n  } else {\n    child.stdin.end();\n  }\n\n  let timeout: NodeJS.Timeout | undefined;\n  if (invocation.timeoutMs && invocation.timeoutMs > 0) {\n    timeout = setTimeout(() => child.kill('SIGTERM'), invocation.timeoutMs);\n  }\n\n  const exitPromise = once(child, 'exit') as Promise<[number | null, NodeJS.Signals | null]>;\n  const errorPromise = once(child, 'error').then(([error]) => {\n    throw error;\n  }) as Promise<[number | null, NodeJS.Signals | null]>;\n  const [exitCode, signal] = await Promise.race([exitPromise, errorPromise]);\n  if (timeout) clearTimeout(timeout);\n\n  if (exitCode !== 0) {\n    throw new Error(\n      [\n        `Local command failed for ${context.finalSlug}: ${invocation.command} ${(invocation.args ?? []).join(' ')}`,\n        `exitCode=${exitCode ?? 'null'} signal=${signal ?? 'null'}`,\n        stderr.trim() ? `stderr: ${stderr.trim()}` : undefined,\n      ]\n        .filter(Boolean)\n        .join('\\n')\n    );\n  }\n\n  return {\n    command: invocation.command,\n    args: invocation.args ?? [],\n    stdout,\n    stderr,\n    exitCode,\n    parsed: parseJsonIfRequested(stdout, execution.parseJson ?? false),\n  };","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/cli-local-tools/src/runtime.ts#L124-L160","documentation":"The spawned local command exited with a non-zero exit code (or was killed by a signal). The error aggregates the full command line, exitCode, signal, and trimmed stderr so the underlying CLI failure is visible. This is a wrapper for any downstream executable failure, not an SDK bug per se.","triggerScenarios":"The external tool (e.g. sqlite3, imessage-export, a git helper) exits non-zero due to bad input, missing permissions, or missing runtime; the process is killed by SIGTERM/SIGKILL (timeout, OOM).","commonSituations":"Missing macOS Full Disk Access permission for terminal reading iMessage DB; the external helper binary not installed; sandboxed environments killing subprocesses; invalid arguments passed through to the child process.","solutions":["Read the stderr line in the message — it is the downstream tool's actual error","Fix the environmental cause (install helper, grant permissions, fix args)","Check exitCode/signal: signal=SIGTERM often means a timeout kill","Wrap the call and surface stderr to the user instead of the generic wrapper"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { const res = await executeLocalTool(slug, args, ctx); } catch (e) { if (e instanceof Error && e.message.includes('Local command failed')) { console.error(e.message); // includes stderr, exitCode, signal } }","preventionTips":["Ensure helper binaries and OS permissions (Full Disk Access) exist","Parse stderr from the message for actionable downstream errors"],"tags":["subprocess","exit-code","local-tools","cli"],"backgroundTag":"command-exit-nonzero","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}