JuliusBrussee/caveman · error

Claude usage refresh needs CAVEMAN_CLAUDE_USAGE_JSON or CAVE

Error message

Claude usage refresh needs CAVEMAN_CLAUDE_USAGE_JSON or CAVEMAN_CLAUDE_SESSION_KEY plus CAVEMAN_CLAUDE_ORG_ID

What it means

When CAVEMAN_CLAUDE_USAGE_JSON is not set, fetchClaudeUsageJSON tries the live claude.ai usage endpoint and requires both CAVEMAN_CLAUDE_SESSION_KEY (browser session cookie value) and CAVEMAN_CLAUDE_ORG_ID. Missing either yields this fail-fast configuration error before any HTTP request is made — no anonymous or partial fetch exists.

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 27d5a3981a)

Solutions

  1. Export both variables: CAVEMAN_CLAUDE_SESSION_KEY=<sessionKey cookie value> and CAVEMAN_CLAUDE_ORG_ID=<org uuid>.
  2. Prefer the offline path if you already have the JSON: set CAVEMAN_CLAUDE_USAGE_JSON instead and skip credential handling.
  3. Verify with: [ -n "$CAVEMAN_CLAUDE_SESSION_KEY" ] && [ -n "$CAVEMAN_CLAUDE_ORG_ID" ] && echo ok.
  4. Check for typos/trailing whitespace in the variable names and values in your env file.

Example fix

# before
export CAVEMAN_CLAUDE_SESSION_KEY=sk-ant-sid-...
# org id missing -> error

# after
export CAVEMAN_CLAUDE_SESSION_KEY=sk-ant-sid-...
export CAVEMAN_CLAUDE_ORG_ID=0f1e2d3c-4b5a-6978-8796-a5b4c3d2e1f0
Defensive patterns

Strategy: validation

Validate before calling

func claudeUsageCredsReady() bool {
    if os.Getenv("CAVEMAN_CLAUDE_USAGE_JSON") != "" {
        return true
    }
    return os.Getenv("CAVEMAN_CLAUDE_SESSION_KEY") != "" &&
        os.Getenv("CAVEMAN_CLAUDE_ORG_ID") != ""
}

if !claudeUsageCredsReady() {
    return errors.New("set CAVEMAN_CLAUDE_USAGE_JSON, or both SESSION_KEY and ORG_ID")
}

Try / catch

if _, err := s.RefreshClaudeUsageFromEnv(); err != nil {
    if strings.Contains(err.Error(), "CAVEMAN_CLAUDE_SESSION_KEY") {
        return configError("export CAVEMAN_CLAUDE_SESSION_KEY and CAVEMAN_CLAUDE_ORG_ID (or CAVEMAN_CLAUDE_USAGE_JSON)")
    }
    return err
}

Prevention

When it happens

Trigger: Running the usage refresh with only CAVEMAN_CLAUDE_SESSION_KEY exported, only CAVEMAN_CLAUDE_ORG_ID, or neither; a systemd/CI unit that does not import the file where these are defined.

Common situations: Operator sets the session key but never noted the org id (visible in the claude.ai URL or settings); env vars defined in an interactive shell but the import runs from cron; the session key env name is typo'd so both appear unset.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/3eef29d0b056fed1. Report an issue: GitHub.