JuliusBrussee/caveman · error

unknown usage link source

Error message

unknown usage link source: %s

What it means

Thrown by runUsage's `link`/`refresh` branch: the provider positional must be empty, `claude`, or `codex` (empty defaults to claude). Any other value hits `unknown usage link source: <provider>` because those subcommands only know how to refresh Claude usage from environment credentials or import Codex usage from local files.

Solutions

  1. Use `caveman-proxy usage link claude` or `caveman-proxy usage link codex`.
  2. Omit the provider entirely to default to claude: `caveman-proxy usage refresh`.
  3. Map `anthropic`→`claude` and `openai`→`codex` in any wrapper scripts.

Example fix

// before
caveman-proxy usage refresh anthropic
// after
caveman-proxy usage refresh claude   # or just: caveman-proxy usage refresh
Defensive patterns

Strategy: validation

Validate before calling

// shell
case "$PROVIDER" in ""|claude|codex) ;; anthropic) PROVIDER=claude;; openai) PROVIDER=codex;; *) echo "link/refresh supports claude|codex only" >&2; exit 2;; esac
caveman-proxy usage refresh "$PROVIDER"

Prevention

When it happens

Trigger: `caveman-proxy usage link gemini`, `usage refresh anthropic` (not accepted here even though `unlink` accepts it), `usage link openai`, or typos.

Common situations: Confusing the accepted provider sets between subcommands: `link`/`refresh` take claude|codex (or nothing), `unlink` also accepts anthropic/openai aliases, `import` requires an explicit claude|codex; running `refresh anthropic` expecting the alias to carry over.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

		default:
			fatalJSON(logger, fmt.Errorf("unknown usage source: %s", provider))
		}
	case "link", "refresh":
		switch provider {
		case "", "claude":
			out, err := spend.RefreshClaudeUsageFromEnv()
			if err != nil {
				fatalJSON(logger, err)
			}
			printJSON(out)
		case "codex":
			out, err := spend.ImportCodex(argFlag(args, "--path", ""), argFlag(args, "--since", ""))
			if err != nil {
				fatalJSON(logger, err)
			}
			printJSON(out)
		default:
			fatalJSON(logger, fmt.Errorf("unknown usage link source: %s", provider))
		}
	case "unlink":
		switch provider {
		case "claude", "anthropic":
			if err := spend.DeleteQuotaProvider("anthropic"); err != nil {
				fatalJSON(logger, err)
			}
			printJSON(map[string]any{"unlinked": "claude"})
		case "codex", "openai":
			if err := spend.DeleteQuotaProvider("openai"); err != nil {
				fatalJSON(logger, err)
			}
			printJSON(map[string]any{"unlinked": "codex"})
		default:
			fatalJSON(logger, fmt.Errorf("usage unlink needs claude|codex"))
		}
	default:
		fatalJSON(logger, fmt.Errorf("unknown usage subcommand: %s", sub))

View on GitHub (pinned to 3ee70a1026)