JuliusBrussee/caveman · error · Error

choose --days or --all-time

Error message

choose --days or --all-time

What it means

Option conflict in parseStatsOptions: the stats window must be unambiguous, so --days (bounded recent window) and --all-time (full history) cannot both be passed. Neither is defaulted when the other is present, and both together are rejected.

Solutions

  1. Remove one of the two flags depending on the desired window
  2. If you want everything, keep only `--all-time`; for a bounded window keep only `--days N`
  3. In wrapper scripts, strip --all-time before appending --days (or vice versa)

Example fix

// before
myapp stats --days 30 --all-time
// after
myapp stats --days 30
Defensive patterns

Strategy: validation

Validate before calling

const a = argv.filter(x => x !== "--all-time");
if (a.includes("--days") && argv.includes("--all-time")) throw new Error("pass --days or --all-time, not both");

Try / catch

try {
  const opts = parseStatsOptions(argv);
} catch (e) {
  if (e.message === "choose --days or --all-time") {
    console.error(e.message); process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: `stats --days 30 --all-time`; a wrapper script appending --all-time on top of user-supplied --days.

Common situations: Defaults injected by tooling colliding with user flags; misunderstanding that --all-time overrides --days (it doesn't — it's rejected).

Understand the failure class

Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/9229175f0264ab34. Report an issue: GitHub.

Appendix: source

Thrown at packages/cli/src/stats-cli.ts:54

  for (let i = 0; i < argv.length; i++) {
    const arg = argv[i]!;
    if (seen.has(arg)) throw new Error(`duplicate ${arg}`);
    seen.add(arg);
    if (valueFlags.has(arg)) {
      const value = argv[++i];
      if (!value || value.startsWith("--") || /[\u0000-\u001f\u007f]/u.test(value)) throw new Error(`${arg} requires a value`);
      if (arg === "--days" && (!/^\d+$/u.test(value) || Number(value) < 1 || Number(value) > 3660)) {
        throw new Error("--days must be an integer from 1 to 3660");
      }
      if (arg === "--out") result.out = value;
      else result.filters.push(arg, value);
    } else if (arg === "--json") result.json = true;
    else if (arg === "--plain" || arg === "--no-open") result.plain = true;
    else if (arg === "--open") result.open = true;
    else if (arg === "--all-time") result.filters.push("--days", "0");
    else throw new Error(`unknown option ${arg}`);
  }
  if (seen.has("--days") && seen.has("--all-time")) throw new Error("choose --days or --all-time");
  if (result.plain && result.open) throw new Error("choose --plain or --open");
  if (result.json && result.open) throw new Error("--json cannot open a browser");
  return result;
}

type StatsMetrics = {
  requests: number;
  successful_requests: number;
  failed_requests: number;
  input_tokens: number;
  output_tokens: number;
  cache_read_tokens: number;
  cache_write_tokens: number;
  complete_usage_requests: number;
  partial_usage_requests: number;
  measured_requests: number;
  unmeasured_requests: number;
  before_tokens: number;

View on GitHub (pinned to 3ee70a1026)