JuliusBrussee/caveman · error · Error

caveman compress --toon-stats is unavailable; use --toon to

Error message

caveman compress --toon-stats is unavailable; use --toon to force TOON compression

What it means

Guard against a removed flag. Older CLI builds exposed `caveman compress --toon-stats` to print TOON compression statistics; current builds emit the engine's JSON ratio report to stderr automatically, so the flag was deleted. Passing it now throws before stdin is even read, failing fast instead of silently compressing differently than the caller intended.

Source

Thrown at packages/cli/src/index.ts:12920

function writeMcpMarker(agentId: string, mcp: { command: string; args: string[] }): void {
  writeMcpServerMarker(agentId, "caveman", mcp, "caveman_retrieve");
}

function writeMcpServerMarker(agentId: string, serverName: string, mcp: { command: string; args: string[] }, tool: string): void {
  const path = mcpServerMarkerPath(agentId, serverName);
  durableAtomicWriteFile(path, mcpMarkerBytes(mcp, tool));
}

// compress streams stdin through the caveman-engine binary (resolved via
// CAVEMAN_ENGINE_BIN, default `caveman-engine` on PATH) and writes the compressed
// payload to stdout, forwarding the engine's JSON ratio report to stderr. The
// engine is fail-closed; if its binary is unavailable the CLI falls back to a
// pass-through that claims a 0 ratio, so `compress` never breaks a pipe.
async function compress(argv: string[]) {
  if (argv[0] === "catalog") return compressCatalog(argv.slice(1));
  if (argv.includes("--toon-stats")) {
    throw new Error("caveman compress --toon-stats is unavailable; use --toon to force TOON compression");
  }
  const input = await readStdin();
  const bin = cavemanBin("caveman-engine", "CAVEMAN_ENGINE_BIN");
  const typeIndex = argv.indexOf("--type");
  if (typeIndex >= 0 && (argv[typeIndex + 1] === undefined || argv[typeIndex + 1]!.startsWith("--"))) {
    throw new Error(`usage: ${invokedCommand("compress")} [--type <content-type>] [--toon]`);
  }
  let forcedType = argv.includes("--toon") ? "toon" : flagFrom(argv, "--type", "");
  if (forcedType === "auto") forcedType = "";
  const engineArgs = ["compress"];
  if (forcedType) engineArgs.push("--type", forcedType);
  let handled = false;
  const child = spawn(bin, engineArgs, { stdio: ["pipe", "inherit", "inherit"] });
  emitCommandRunOnce("ok"); // exit handler below hard-exits; never returns to main()
  child.on("error", () => { if (!handled) { handled = true; compressFallback(input, forcedType); } });
  child.on("exit", (code) => { if (!handled) { handled = true; process.exit(code ?? 0); } });
  if (child.stdin) {
    child.stdin.on("error", () => {}); // ignore broken pipe; the child 'error' drives the fallback

View on GitHub (pinned to 5184b3d11a)

Solutions

  1. Replace `--toon-stats` with `--toon` — it forces TOON compression and the ratio report still lands on stderr
  2. Drop the flag entirely if you only wanted the stats; they are printed by default
  3. Pin the CLI version in CI until all scripts are updated

Example fix

# before
cat payload.json | caveman compress --toon-stats
# after
cat payload.json | caveman compress --toon   # ratio report still goes to stderr
Defensive patterns

Strategy: validation

Validate before calling

// Probe flag support before the pipeline step runs.
import { execSync } from 'node:child_process';
const help = execSync('caveman compress --help 2>&1', { encoding: 'utf8' });
if (!/--toon\b/.test(help)) throw new Error('caveman CLI too old — upgrade before compressing');

Try / catch

catch (e) {
  if ((e as Error).message.includes('--toon-stats')) {
    // rerun with `--toon`; ratio stats still arrive on stderr
  } else throw e;
}

Prevention

When it happens

Trigger: Any invocation containing `--toon-stats` (checked with argv.includes), typically a script, Makefile, or CI step written against an older CLI version. The flag throws even when combined with otherwise valid options like --type.

Common situations: CLI upgraded globally or in a Docker image while CI scripts still pass the old flag; commands copy-pasted from outdated docs; team members on different CLI versions.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@5184b3d11a (2026-08-18). Data as JSON: /api/errors/3cc4b38bdbb17f1c. Report an issue: GitHub.