JuliusBrussee/caveman · error
Claude usage refresh needs CAVEMAN_CLAUDE_USAGE_JSON or…
Error message
Claude usage refresh needs CAVEMAN_CLAUDE_USAGE_JSON or CAVEMAN_CLAUDE_SESSION_KEY plus CAVEMAN_CLAUDE_ORG_ID
What it means
fetchClaudeUsageJSON requires either CAVEMAN_CLAUDE_USAGE_JSON with inline data or both CAVEMAN_CLAUDE_SESSION_KEY and CAVEMAN_CLAUDE_ORG_ID to fetch usage from claude.ai. When the session key or org id is missing/empty, refresh cannot proceed and throws this error instead of making a doomed request.
Solutions
- Export both CAVEMAN_CLAUDE_SESSION_KEY and CAVEMAN_CLAUDE_ORG_ID
- Alternatively set CAVEMAN_CLAUDE_USAGE_JSON with the usage document to skip fetching
- Check env var spelling in your shell profile / CI secrets config
- Prefer inline JSON in air-gapped environments where claude.ai is unreachable
Example fix
// before export CAVEMAN_CLAUDE_SESSION_KEY=sk-... # ORG_ID missing // after export CAVEMAN_CLAUDE_SESSION_KEY=sk-... export CAVEMAN_CLAUDE_ORG_ID=org-abc123
Defensive patterns
Strategy: validation
Validate before calling
missing := []string{}
if os.Getenv("CAVEMAN_CLAUDE_USAGE_JSON") == "" {
if os.Getenv("CAVEMAN_CLAUDE_SESSION_KEY") == "" { missing = append(missing, "CAVEMAN_CLAUDE_SESSION_KEY") }
if os.Getenv("CAVEMAN_CLAUDE_ORG_ID") == "" { missing = append(missing, "CAVEMAN_CLAUDE_ORG_ID") }
}
if len(missing) > 0 { return fmt.Errorf("missing env: %v", missing) } Try / catch
if err := runUsage(); err != nil {
if strings.Contains(err.Error(), "needs CAVEMAN_CLAUDE") {
// print setup instructions
}
} Prevention
- Document required env vars in setup docs and CI secrets
- Check env presence at process startup with a config linter
- Prefer a .env file loader with required-key validation
When it happens
Trigger: Running the usage refresh (runUsage -> RefreshClaudeUsageFromEnv) with neither CAVEMAN_CLAUDE_USAGE_JSON set nor the CAVEMAN_CLAUDE_SESSION_KEY/CAVEMAN_CLAUDE_ORG_ID pair complete — e.g. only one of the two env vars set, or both empty.
Common situations: Fresh machine or CI where Claude credentials were never exported; setting SESSION_KEY but forgetting ORG_ID; typo'd env var names; secrets stripped by the deployment environment.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- CAVE_SETUP_TIMEOUT must be a positive integer
- caveman agent: multiple provider credentials found; set…
- caveman build: set CAVE_MODEL when zero or multiple…
- does not point to an executable
- multiple provider credentials detected; pass --provider
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/3eef29d0b056fed1.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/internal/store/usage_import.go:131
raw = string(fetched)
}
var v any
if err := json.Unmarshal([]byte(raw), &v); err != nil {
return ImportSummary{}, fmt.Errorf("parse Claude usage JSON: %w", err)
}
quotas := quotaEventsFromAny("anthropic", "claude_usage_link", "linked_api", time.Now().UTC().Format(time.RFC3339), v)
n, err := s.InsertQuotaEvents(quotas)
if err != nil {
return ImportSummary{}, err
}
return ImportSummary{Source: "claude", QuotaImported: n, Basis: "linked_api"}, nil
}
func fetchClaudeUsageJSON() ([]byte, error) {
sessionKey := os.Getenv("CAVEMAN_CLAUDE_SESSION_KEY")
orgID := os.Getenv("CAVEMAN_CLAUDE_ORG_ID")
if sessionKey == "" || orgID == "" {
return nil, fmt.Errorf("Claude usage refresh needs CAVEMAN_CLAUDE_USAGE_JSON or CAVEMAN_CLAUDE_SESSION_KEY plus CAVEMAN_CLAUDE_ORG_ID")
}
if strings.Contains(orgID, "/") || strings.Contains(orgID, "..") {
return nil, fmt.Errorf("invalid Claude organization id")
}
req, err := http.NewRequest("GET", "https://claude.ai/api/organizations/"+orgID+"/usage", nil)
if err != nil {
return nil, err
}
req.Header.Set("accept", "application/json")
req.Header.Set("cookie", "sessionKey="+sessionKey)
client := http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, fmt.Errorf("Claude usage request failed with HTTP %d", resp.StatusCode)View on GitHub (pinned to 3ee70a1026)