JuliusBrussee/caveman · error · Error

caveman-code: host command shell is not available

Error message

caveman-code: host command shell is not available

What it means

The bash tool spawns the host shell produced by `hostShellInvocation` (platform-dependent /bin/bash or sh). If that shell binary cannot be spawned at all (ENOENT/EPERM), the run is marked spawnFailed and this error is thrown. It is an environment capability failure, not a failure of the command itself.

Source

Thrown at packages/agent/src/code.ts:316

      `Times out after ${BASH_TIMEOUT_MS} ms; output is capped at ${caps.bash} bytes.`,
    input: schema.object({
      command: schema.string(),
      timeoutMs: schema.optional(schema.integer()),
    }),
    effect: "external",
    result: "inline",
    timeoutMs: BASH_TIMEOUT_MS,
    async execute(input, signal) {
      const timeoutMs = Math.min(input.timeoutMs ?? BASH_TIMEOUT_MS, BASH_TIMEOUT_MS);
      const shell = hostShellInvocation(input.command, process.platform, buildCodingProcessEnv());
      const run = await runProcess(
        shell.command,
        shell.args,
        await workspaceRoot(),
        timeoutMs,
        signal,
      );
      if (run.spawnFailed) throw new Error("caveman-code: host command shell is not available");
      const body = [
        `exit ${run.timedOut ? `timeout after ${timeoutMs}ms` : run.code}`,
        run.output.trim() === "" ? "(no output)" : run.output,
      ].join("\n");
      const text = capOutput(body, caps.bash);
      record(`bash:${input.command.slice(0, 60)}`, text);
      return text;
    },
  });

  const editTool = tool({
    name: "edit_file",
    description:
      "Replace an exact string in a workspace file. The old string must appear exactly " +
      "once unless replace_all is set. Writes to disk.",
    input: schema.object({
      path: schema.string(),
      old_string: schema.string(),

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Ensure a POSIX shell (bash or sh) exists and is executable in the agent's runtime environment; on Windows install Git Bash or WSL and make it reachable
  2. Check that the process env passed to the agent does not clobber PATH — buildCodingProcessEnv may sanitize it, so keep the shell's directory on the sanitized PATH
  3. If the host genuinely has no shell, route work to the other tools (edit_file, grep) instead of bash, or run the agent in a proper container
  4. Verify spawn capability directly: `node -e "require('child_process').spawnSync(process.platform==='win32'?'bash':'/bin/sh',['-c','echo ok'])"` in the same environment

Example fix

// before: PATH sanitized to empty, shell unresolvable
env: { PATH: "" }

// after: keep system dirs on PATH so hostShellInvocation can spawn
env: { PATH: "/usr/local/bin:/usr/bin:/bin" }
Defensive patterns

Strategy: validation

Validate before calling

import { spawnSync } from "node:child_process";

function shellAvailable(): boolean {
  const shell = process.platform === "win32" ? "bash" : "/bin/sh";
  return spawnSync(shell, ["-c", "true"]).error === undefined;
}

if (!shellAvailable()) throw new Error("no host shell; bash tool disabled");

Try / catch

try {
  const res = await bashTool.execute({ command }, signal);
} catch (err) {
  if (err instanceof Error && err.message.includes("host command shell is not available")) {
    // do not retry the command; fix the environment instead
    throw new Error(`shell missing on host (${process.platform}); install bash/sh`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Invoking the `bash` tool on a host without a usable shell binary: Windows without bash (only cmd/powershell exist), containers with no shell, or environments where buildCodingProcessEnv() strips PATH entries containing the shell, or execute permissions deny spawning it.

Common situations: Windows deployments (no /bin/bash); minimal/distroless containers; macOS sandbox-exec profiles blocking /bin/sh; a PATH env var overwritten to a directory set that excludes /bin and /usr/bin.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/37c40253d61d80ed. Report an issue: GitHub.