JuliusBrussee/caveman · error
%s: provider, model, and region are required
Error message
%s: provider, model, and region are required
What it means
Thrown by the pricing catalog YAML loader when an entry has an empty (or whitespace-only) provider, model, or region field after trimming. Every catalog row must be fully identified so pricing lookups key on provider+model+region; a row missing any part is rejected at load time.
Source
Thrown at shared/platform/catalog/catalog.go:264
var decoded []Entry
if err := dec.Decode(&decoded); err != nil {
return nil, err
}
var trailing any
if err := dec.Decode(&trailing); err != io.EOF {
if err == nil {
return nil, fmt.Errorf("multiple YAML documents are not allowed")
}
return nil, err
}
if len(decoded) == 0 {
return nil, fmt.Errorf("catalog is empty")
}
seen := make(map[string]struct{}, len(decoded))
for i, entry := range decoded {
label := fmt.Sprintf("entry %d", i)
if strings.TrimSpace(entry.Provider) == "" || strings.TrimSpace(entry.Model) == "" || strings.TrimSpace(entry.Region) == "" {
return nil, fmt.Errorf("%s: provider, model, and region are required", label)
}
if entry.Currency != "USD" {
return nil, fmt.Errorf("%s %s/%s: unsupported currency %q", label, entry.Provider, entry.Model, entry.Currency)
}
if !cost.ValidPrice(entry.Pricing) {
return nil, fmt.Errorf("%s %s/%s: invalid pricing", label, entry.Provider, entry.Model)
}
verified, err := time.Parse(time.RFC3339, entry.VerifiedAt)
if err != nil || verified.IsZero() {
return nil, fmt.Errorf("%s %s/%s: verified_at must be RFC3339", label, entry.Provider, entry.Model)
}
if verified.After(time.Now().UTC().Add(24 * time.Hour)) {
return nil, fmt.Errorf("%s %s/%s: verified_at is in the future", label, entry.Provider, entry.Model)
}
if entry.CapabilitiesVerifiedAt != "" {
capVerified, err := time.Parse(time.RFC3339, entry.CapabilitiesVerifiedAt)
if err != nil || capVerified.IsZero() {
return nil, fmt.Errorf("%s %s/%s: capabilities_verified_at must be RFC3339", label, entry.Provider, entry.Model)View on GitHub (pinned to 27d5a3981a)
Solutions
- Open the catalog YAML at the entry index in the error message and fill in provider, model, and region (all non-empty after trimming).
- For providers without a meaningful region, use the project's conventional region value used by sibling entries rather than leaving it blank.
- If generated, fix the generator to require all three fields per row and re-run.
Example fix
# before - provider: anthropic model: claude-sonnet-4 region: "" # after - provider: anthropic model: claude-sonnet-4 region: us
Defensive patterns
Strategy: validation
Validate before calling
func validCatalogEntry(e Entry) bool {
return strings.TrimSpace(e.Provider) != "" &&
strings.TrimSpace(e.Model) != "" &&
strings.TrimSpace(e.Region) != ""
} Try / catch
Catch catalog load errors at startup and fail fast with the file path + entry index; do not run with a partial catalog.
Prevention
- Validate catalog edits in CI (a test that loads the YAML) before merge.
- Generate entries from structured data instead of hand-editing YAML.
- Treat 'entry N' in the error as a 0-based list index to jump straight to the row.
When it happens
Trigger: A catalog YAML entry like {provider: "", model: "claude-...", region: "us-east-1"}, or one where region is absent entirely (YAML omits missing keys as empty strings). The error names the offending entry by its 0-based index ('entry N').
Common situations: Hand-editing the catalog YAML and dropping a field; a generator script emitting rows with missing region for providers that have none (e.g. forgetting a default like 'us' or 'global'); copy-paste of a row that deletes the region line.
Related errors
- ${label}: ${key} has no pricing block
- %s %s/%s: unsupported currency %q
- %s %s/%s: invalid pricing
- ${label}:${lineNo}: "${text}" is not a finite number
- ${label}: row is missing a string "${field}"
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/dcb7f549a73d9f6b.
Report an issue: GitHub.