JuliusBrussee/caveman · error

usage: caveman-proxy learn apply

Error message

usage: caveman-proxy learn apply <sink_id> [--dry-run]

What it means

Thrown by runLearn's `apply` branch when no positional sink id is given: `caveman-proxy learn apply <sink_id> [--dry-run]`. The apply path builds a learn plan and materializes a candidate edit for the named sink, so it cannot proceed without an id.

Solutions

  1. Run `caveman-proxy learn scan` (or `learn report --json`) and copy a sink_id from plan.sinks.
  2. Invoke: `caveman-proxy learn apply <sink_id> --dry-run` first to preview the candidate without writing.
  3. Remember the id is a bare positional, not a --sink-id flag.

Example fix

// before
caveman-proxy learn apply --dry-run
// after
caveman-proxy learn apply context-overload-7f3a --dry-run
Defensive patterns

Strategy: validation

Validate before calling

// shell
if [ -z "$SINK_ID" ]; then echo "learn apply requires a positional sink_id" >&2; exit 2; fi
caveman-proxy learn apply "$SINK_ID" --dry-run

Prevention

When it happens

Trigger: `caveman-proxy learn apply`, or `learn apply --dry-run` where `--dry-run` is a flag, not the positional, so firstPositional(args) still returns empty.

Common situations: Running apply without first inspecting `learn scan`/`learn report` output to obtain a sink_id; assuming flags alone are enough; pasting only `--dry-run` from docs and forgetting the id.

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@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/d63e40dfbc7acf02. Report an issue: GitHub.

Appendix: source

Thrown at proxy/cmd/caveman-proxy/main.go:729

		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 "savings":
		savings, err := spend.BuildLearnSavings(cwd, sources, since)
		if err != nil {
			fatalJSON(logger, err)
		}
		printJSON(savings)
	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)
	case "applied":
		sinkID := firstPositional(args)
		if sinkID == "" {
			fatalJSON(logger, fmt.Errorf("usage: caveman-proxy learn applied <sink_id> [--fix-kind <k>] [--note <s>]"))
		}
		plan, err := spend.BuildLearnPlanFilteredWithRetro(cwd, sources, since, store.RetroOptions{}, repoFilter)
		if err != nil {
			fatalJSON(logger, err)
		}
		recorded, err := spend.RecordAppliedFix(plan, sinkID, argFlag(args, "--fix-kind", ""), argFlag(args, "--note", ""))
		if err != nil {
			fatalJSON(logger, err)

View on GitHub (pinned to 3ee70a1026)