JuliusBrussee/caveman · error
parse Claude usage JSON: %w
Error message
parse Claude usage JSON: %w
What it means
RefreshClaudeUsageFromEnv imports Claude usage/quota data from CAVEMAN_CLAUDE_USAGE_JSON (inline JSON) or, when that env is empty, from a live fetch of claude.ai. This error means the resulting string was not valid JSON — json.Unmarshal failed and the parse error is wrapped with this message. It guards the store from inserting garbage quota events.
Source
Thrown at proxy/internal/store/usage_import.go:117
if event.Basis != observedLocal && event.Basis != "observed_provider" {
return "estimated"
}
}
return observedLocal
}
func (s *Store) RefreshClaudeUsageFromEnv() (ImportSummary, error) {
raw := os.Getenv("CAVEMAN_CLAUDE_USAGE_JSON")
if raw == "" {
fetched, err := fetchClaudeUsageJSON()
if err != nil {
return ImportSummary{}, err
}
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")
}View on GitHub (pinned to 27d5a3981a)
Solutions
- Validate the payload first: echo "$CAVEMAN_CLAUDE_USAGE_JSON" | jq . — fix whatever jq reports.
- Re-capture the payload from the live endpoint (curl the usage URL) so you have a complete, current document.
- Use a single-quoted heredoc or write the JSON to a file and export via $(cat file) with proper quoting to avoid shell mangling.
- If you meant to use the live fetch path, unset CAVEMAN_CLAUDE_USAGE_JSON entirely instead of leaving a broken value.
Example fix
# before
export CAVEMAN_CLAUDE_USAGE_JSON='{"costs": [} # malformed
# after
export CAVEMAN_CLAUDE_USAGE_JSON=$(cat usage.json) # jq-validated file
# sanity check before running the import:
jq -e . usage.json >/dev/null && echo OK Defensive patterns
Strategy: validation
Validate before calling
if raw := os.Getenv("CAVEMAN_CLAUDE_USAGE_JSON"); raw != "" {
if !json.Valid([]byte(raw)) {
return errors.New("CAVEMAN_CLAUDE_USAGE_JSON is not valid JSON; validate with jq")
}
}
summary, err := s.RefreshClaudeUsageFromEnv() Type guard
func isValidUsageJSON(raw string) bool {
var v any
return json.Unmarshal([]byte(raw), &v) == nil
} Try / catch
summary, err := s.RefreshClaudeUsageFromEnv()
if err != nil {
if strings.Contains(err.Error(), "parse Claude usage JSON") {
return errors.New("usage payload malformed: re-capture from the endpoint and jq -e validate it")
}
return err // credential/network errors have different fixes
} Prevention
- Always jq -e validate captured payloads before exporting them.
- Store payloads in files and export via $(cat file) with correct quoting.
- Unset the env var rather than leaving a broken value if switching to live fetch.
When it happens
Trigger: Setting CAVEMAN_CLAUDE_USAGE_JSON to a truncated, HTML (login page), or otherwise malformed payload; exporting it with shell quoting that strips or mangles characters; a proxied fetch that returned an error body that was saved verbatim.
Common situations: Copy-pasting JSON into an export line and losing closing braces; writing the env var from a script that captured a curl error page instead of the API response; BOM or whitespace-sensitive pipelines; the upstream API changed shape and the saved fixture predates it.
Related errors
- Claude usage refresh needs CAVEMAN_CLAUDE_USAGE_JSON or CAVE
- corpus provider conversion supports string or null content
- cachebench: verifier returned duplicate or invalid JSON
- cachebench: verifier returned invalid JSON
- cacheengine: JSON nesting limit exceeded
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/cf92117dc6027926.
Report an issue: GitHub.