{"record":{"id":"7cb0c12aaf6e91ea","repo":"JuliusBrussee/caveman","slug":"failed-to-exec-bin-result-error-message","errorCode":null,"errorMessage":"failed to exec ${bin}: ${result.error.message}","messagePattern":"failed to exec (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":5028,"sourceCode":"async function agentShortcut(rest: string[]) {\n  // normalizeAgentShortcutWrapArgs hoists --off/--pixel/--workflow to the\n  // front, so a leading flag means explicit session-only wrap intent.\n  if (rest[0]?.startsWith(\"--\")) return wrap(rest);\n  const agent = findAgent(rest[0] ?? \"\");\n  const native = agent ? nativeAgentId(agent.id) : undefined;\n  if (!agent || !native) return wrap(rest);\n  // Host help is observational. Never turn `caveman claude --help` into a\n  // machine-wide integration install before printing another program's usage.\n  if (rest.slice(1).some((arg) => arg === \"--help\" || arg === \"-h\")) {\n    const bin = which(binOf(agent));\n    if (!bin) {\n      wrapNotFoundUI(rest[0]!, agent);\n      process.exitCode = 127;\n      return;\n    }\n    const invocation = portableInvocation(bin, [...agent.args, ...rest.slice(1)]);\n    const result = spawnSync(invocation.command, invocation.args, { stdio: \"inherit\" });\n    if (result.error) throw new Error(`failed to exec ${bin}: ${result.error.message}`);\n    process.exitCode = result.status ?? 1;\n    return;\n  }\n  // A Cave Build lock is enforced at the wrap door (claudeCaveBuildEnv); the\n  // native door applies none of its transforms, so a locked project must keep\n  // routing through wrap or the lock would be silently unenforced.\n  if (existsSync(join(process.cwd(), \".caveman\", \"agent.lock.json\"))) return wrap(rest);\n  // First-run disclosure comes before the first persistent write, mirroring wrap.\n  await firstRunExperience();\n  try {\n    // An existing journal means the machine-wide install already owns routing —\n    // exactly what plain `<agent>` uses — so launch directly without re-probing\n    // (status probes spawn three subprocesses); `caveman doctor <agent>` stays\n    // the repair door for drifted installs.\n    if (!readNativeJournal(native)) enableNative([native]);\n  } catch (error) {\n    process.stderr.write(`${mark(\"warn\")} native enable failed: ${(error as Error).message} — using session-only wrap for this run\\n`);\n    return wrap(rest);","sourceCodeStart":5010,"sourceCodeEnd":5046,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/5184b3d11ac6a1acb7d44b9bfaa31698157cff97/packages/cli/src/index.ts#L5010-L5046","documentation":"This error is thrown by the CLI when spawning a child process (an agent binary) fails at the OS level — i.e. spawnSync populated result.error. The library throws it to surface the underlying Node spawn failure (e.g. ENOENT, EACCES) with the binary name for context.","triggerScenarios":"Running a subcommand that resolves to a binary (via portableInvocation) where the executable does not exist at the resolved path, lacks execute permission, or otherwise cannot be spawned by spawnSync.","commonSituations":"Agent CLI not installed or not on PATH; PATH differs inside wrappers/non-interactive shells; binary installed for a different platform/architecture; permissions lost after copying a binary; antivirus or sandbox blocking exec.","solutions":["Verify the binary exists and is executable: `which <bin>` or `ls -l $(which <bin>)`; install it if missing (e.g. `npm i -g <package>`).","Fix PATH so it includes the binary's directory in the shell where the CLI runs (check ~/.zshrc, ~/.bashrc, CI env).","Check file permissions: `chmod +x <path-to-bin>`.","Reinstall the binary for the correct platform/architecture (e.g. wrong-arch Node binary on Apple Silicon vs Intel).","Run the binary directly to see the raw OS error and confirm it starts outside the CLI."],"exampleFix":"// before (binary missing from PATH)\nexport PATH=/usr/local/bin:/usr/bin:/bin\n// after\nexport PATH=\"$HOME/.local/bin:$PATH\"  # ensure agent install dir is on PATH","handlingStrategy":"try-catch","validationCode":"const which = spawnSync(\"which\", [bin]); if (which.status !== 0) throw new Error(`${bin} not found on PATH`);","typeGuard":"function isSpawnError(r: ReturnType<typeof spawnSync>): r is typeof r & { error: Error } { return r.error instanceof Error; }","tryCatchPattern":"try {\n  // run the CLI subcommand that spawns the agent binary\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith(\"failed to exec \")) {\n    console.error(`${e.message} — is the binary installed and on PATH?`);\n    process.exitCode = 127;\n  } else throw e;\n}","preventionTips":["Install all agent binaries before invoking the CLI and verify with `which <bin>`.","Keep install dirs on PATH in non-interactive shells and CI.","After copying binaries, `chmod +x` them.","Pin platform-correct builds (avoid copying binaries across architectures)."],"tags":["spawn","process-execution","cli","enoent"],"backgroundTag":"spawn-enoent","analyzedSha":"5184b3d11ac6a1acb7d44b9bfaa31698157cff97","analyzedAt":"2026-08-31T22:10:17.934Z","contentChangedAt":"2026-08-31T22:10:17.934Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}