Hmbown/CodeWhale · error · SpawnError

spawn_failed

spawn_failed

Error message

docker ${args[0]} timed out

What it means

Thrown by dockerOk() when a docker CLI invocation exceeds its per-command timeout. dockerOk wraps all docker calls used to validate/read the Docker engine state, and any command that neither aborted nor exited but hit its time budget produces this error instead of hanging forever. The message names the docker subcommand that timed out.

Solutions

  1. Check `docker info` in a terminal; if it hangs, restart the Docker daemon / Docker Desktop.
  2. Retry the operation once the engine responds — this is usually transient daemon latency.
  3. If on Colima or a remote DOCKER_HOST, verify the engine is running and reachable (`colima status`, `docker context ls`).
  4. If the command legitimately needs longer, pass a larger timeoutMs in opts to the plugin's docker calls.

Example fix

// before
dockerOk(["image", "inspect", image]); // default timeout, stalls on slow daemon
// after
await dockerOk(["image", "inspect", image], { timeoutMs: 30_000 });
Defensive patterns

Strategy: retry

Validate before calling

// preflight probe
const ok = await dockerAvailable(); // runs docker info with a 10s budget
if (!ok) throw new Error("docker engine not responding");

Try / catch

try {
  await spawnDockerComputer();
} catch (e) {
  if (e?.code === "spawn_failed" && /timed out/.test(e.message)) {
    // wait, confirm `docker info` responds, then retry once
  }
}

Prevention

When it happens

Trigger: Any dockerOk() call (e.g. dockerAvailable's 'docker info' with timeoutMs: 10_000, or 'image inspect' with 15s) where the spawned docker process runs past its timeoutMs and sets r.timedOut.

Common situations: Docker Desktop is starting up or wedged, the docker daemon is unresponsive under heavy load, disk I/O saturation slows the CLI, or a network-attached engine (Colima, remote DOCKER_HOST) is unreachable and the CLI stalls instead of failing fast.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/3f89f5faecc64e18. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/plugins/computer-use/src/spawn.mjs:43

class SpawnError extends ExecError {
  constructor(code, message, result) {
    super(message, result);
    this.code = code;
  }
}

function docker(args, opts = {}) {
  // Docker CLI lives off PATH; on macOS a Colima/Docker-Desktop install puts
  // it in /usr/local/bin or /opt/homebrew/bin which the MCP host's PATH may
  // lack, so try the well-known paths too.
  return run("docker", args, opts);
}

async function dockerOk(args, opts = {}) {
  const r = await docker(args, opts);
  if (r.aborted) throw Object.assign(new ExecError("computer request cancelled", r), { code: "cancelled" });
  if (r.timedOut) throw new SpawnError("spawn_failed", `docker ${args[0]} timed out`, r);
  if (r.code !== 0) throw new SpawnError("spawn_failed", `docker ${args[0]} failed: ${trim(r.stderr || r.stdout)}`, r);
  return r;
}

export async function dockerAvailable(command = docker) {
  const r = await command(["info", "--format", "{{.OSType}}"], { timeoutMs: 10_000 });
  return r.code === 0 && !r.timedOut && !r.aborted && r.stdout.trim() === "linux";
}

/**
 * The image must exist locally. The plugin's own image is built from
 * docker/Dockerfile on first use; any other image name is the caller's
 * responsibility — we never guess a build context for it.
 */
async function ensureImage(image) {
  const inspect = await docker(["image", "inspect", image], { timeoutMs: 15_000 });
  if (inspect.code === 0) return { built: false };
  if (image !== DEFAULT_IMAGE) {

View on GitHub (pinned to 73e0f67d83)