JuliusBrussee/caveman · error
usage: caveman-proxy learn apply <sink_id> [--dry-run]
Error message
usage: caveman-proxy learn apply <sink_id> [--dry-run]
What it means
The `learn apply` subcommand requires a sink_id positional and none was found. fatalJSON prints this usage line (which also documents the optional --dry-run flag) and exits 1 before BuildLearnPlan runs.
Source
Thrown at proxy/cmd/caveman-proxy/main.go:595
fatalJSON(logger, err)
}
out := argFlag(args, "--out", store.DefaultLearnReportPath(home))
if err := spend.WriteLearnHTML(plan, out); err != nil {
fatalJSON(logger, err)
}
sidecar, err := spend.WriteLearnSidecars(home, plan, time.Now(), "")
if err != nil {
fatalJSON(logger, err)
}
if hasArg(args, "--json") {
printJSON(plan)
return
}
printJSON(map[string]any{"report": out, "sidecar": sidecar, "cave_score": plan.CaveScore.Score, "basis": plan.Basis, "sinks": len(plan.Sinks)})
case "apply":
sinkID := firstPositional(args)
if sinkID == "" {
fatalJSON(logger, fmt.Errorf("usage: caveman-proxy learn apply <sink_id> [--dry-run]"))
}
plan, err := spend.BuildLearnPlan(cwd, sources, since)
if err != nil {
fatalJSON(logger, err)
}
applyLearnSink(logger, home, sinkID, hasArg(args, "--dry-run"), plan)
default:
fatalJSON(logger, fmt.Errorf("unknown learn subcommand: %s", sub))
}
}
func learnRetroOptions(args []string) store.RetroOptions {
behaviorBudget, _ := strconv.Atoi(argFlag(args, "--behavior-budget-ms", "0"))
retroBudget, _ := strconv.Atoi(argFlag(args, "--retro-budget-ms", "0"))
return store.RetroOptions{
Enabled: hasArg(args, "--retro"),
BehaviorBudgetMS: behaviorBudget,
BudgetMS: retroBudget,View on GitHub (pinned to 27d5a3981a)
Solutions
- First run learn scan to list sink ids, then pass one: caveman-proxy learn apply <sink_id> --dry-run
- Quote shell variables and assert non-empty in scripts
- Prefer a --dry-run first run to validate the sink id cheaply
Example fix
# before caveman-proxy learn apply --dry-run # after caveman-proxy learn scan # find sink ids caveman-proxy learn apply compress-stdin --dry-run
Defensive patterns
Strategy: validation
Validate before calling
if [ -z "$SINK_ID" ]; then echo "sink id required (see: caveman-proxy learn scan)" >&2; exit 2; fi caveman-proxy learn apply "$SINK_ID" --dry-run
Prevention
- Always learn scan first and copy the sink_id from that output
- One sink per apply invocation; there is no apply-all
- Use --dry-run as a cheap id check before the real run
When it happens
Trigger: `caveman-proxy learn apply --dry-run` with no sink id; flags parsed first leaving no positional; empty SINK shell variable.
Common situations: Copy-pasting the example from the apply docs but dropping the id; assuming apply applies all sinks when none given (it does not — one sink per invocation); quoting bugs eating the argument.
Related errors
- usage: caveman-proxy trial promote <optimizer_id> --trial-id
- unknown trial subcommand: %s
- usage: caveman-proxy usage import|link|refresh|unlink <provi
- usage: caveman-proxy usage import codex|claude
- unknown usage source: %s
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/d63e40dfbc7acf02.
Report an issue: GitHub.