JuliusBrussee/caveman · error · Error

usage: ${invokedCommand("audit")} import --format <fmt> <fil

Error message

usage: ${invokedCommand("audit")} import --format <fmt> <file>

What it means

Usage guard for `caveman audit import`: after skipping the known options (`--format`, `--field-map`), the CLI requires exactly one positional file path pointing at a telemetry export. If no positional argument remains, this usage error is thrown before any file is read or any request is sent. Org/project scope is resolved server-side from the token, so only the file argument is needed.

Source

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

  const body = await post(`/api/v1/projects/${await projectId()}/keys`, { name: flagFrom(argv, "--name", "cli-key"), scopes: ["proxy:write", "sdk:write"] });
  print(body);
}

async function audit(argv: string[]) {
  if (argv[0] === "import") return auditImport(argv);
  if (argv[0] === "eval-import") return auditEvalImport(argv);
  if (argv[0] === "report") return get(`/api/v1/audits/${argv[1] ?? "aud_demo"}`).then(print);
  return post("/api/v1/audits", { last: flagFrom(argv, "--last", "7d") }).then(print);
}

// auditImport reads a telemetry export file and POSTs it to /api/v1/imports.
// Usage: caveman audit import --format <fmt> <file> [--field-map <json>]
// The org/project scope is resolved server-side from the auth token — never
// from the file (tenant-scoped rule).
async function auditImport(argv: string[]) {
  const format = flagFrom(argv, "--format", "caveman-jsonl");
  const file = positionalAfterOptions(argv.slice(1), new Set(["--format", "--field-map"]));
  if (!file) throw new Error(`usage: ${invokedCommand("audit")} import --format <fmt> <file>`);
  const data = await readFile(file);
  const cfg = await config();
  const headers: Record<string, string> = {
    authorization: `Bearer ${cfg.token}`,
    "content-type": "application/octet-stream",
    "x-cave-csrf": "cli"
  };
  const fieldMap = flagFrom(argv, "--field-map", "");
  if (fieldMap) headers["x-cave-field-map"] = fieldMap;
  const response = await fetch(`${cfg.baseURL}/api/v1/imports?format=${encodeURIComponent(format)}`, {
    method: "POST",
    headers,
    body: data
  });
  print(await response.json());
}

// auditEvalImport turns newline-delimited, source-neutral eval records into one

View on GitHub (pinned to 5184b3d11a)

Solutions

  1. Append the export file path: `caveman audit import --format caveman-jsonl ./export.jsonl`
  2. Verify the file variable is non-empty before invoking the CLI
  3. Check the usage line in the error for the expected argument order

Example fix

# before
caveman audit import --format caveman-jsonl ""
# after
caveman audit import --format caveman-jsonl "$EXPORT_FILE"
Defensive patterns

Strategy: validation

Validate before calling

import { access } from 'node:fs/promises';
if (!file || typeof file !== 'string') throw new Error('export file path is required');
await access(file); // surfaces missing files before the CLI runs

Prevention

When it happens

Trigger: `caveman audit import --format caveman-jsonl` with the file path forgotten; the path expanded from an unset/empty shell variable; the path accidentally consumed because it was passed in an option's value position.

Common situations: Long flag-heavy CI commands; copy-paste from docs that used a placeholder like <file>; quoting bugs where $FILE is unset under `set -u`-less scripts.

Understand the failure class

Background: "no subcommand specified" and "... is required": CLI errors when a required argument is missing — this error's family across 13 libraries.

Related errors


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