{"record":{"id":"dcb7f549a73d9f6b","repo":"JuliusBrussee/caveman","slug":"s-provider-model-and-region-are-required","errorCode":null,"errorMessage":"%s: provider, model, and region are required","messagePattern":"(.+?): provider, model, and region are required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/catalog/catalog.go","lineNumber":264,"sourceCode":"\tvar decoded []Entry\n\tif err := dec.Decode(&decoded); err != nil {\n\t\treturn nil, err\n\t}\n\tvar trailing any\n\tif err := dec.Decode(&trailing); err != io.EOF {\n\t\tif err == nil {\n\t\t\treturn nil, fmt.Errorf(\"multiple YAML documents are not allowed\")\n\t\t}\n\t\treturn nil, err\n\t}\n\tif len(decoded) == 0 {\n\t\treturn nil, fmt.Errorf(\"catalog is empty\")\n\t}\n\tseen := make(map[string]struct{}, len(decoded))\n\tfor i, entry := range decoded {\n\t\tlabel := fmt.Sprintf(\"entry %d\", i)\n\t\tif strings.TrimSpace(entry.Provider) == \"\" || strings.TrimSpace(entry.Model) == \"\" || strings.TrimSpace(entry.Region) == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"%s: provider, model, and region are required\", label)\n\t\t}\n\t\tif entry.Currency != \"USD\" {\n\t\t\treturn nil, fmt.Errorf(\"%s %s/%s: unsupported currency %q\", label, entry.Provider, entry.Model, entry.Currency)\n\t\t}\n\t\tif !cost.ValidPrice(entry.Pricing) {\n\t\t\treturn nil, fmt.Errorf(\"%s %s/%s: invalid pricing\", label, entry.Provider, entry.Model)\n\t\t}\n\t\tverified, err := time.Parse(time.RFC3339, entry.VerifiedAt)\n\t\tif err != nil || verified.IsZero() {\n\t\t\treturn nil, fmt.Errorf(\"%s %s/%s: verified_at must be RFC3339\", label, entry.Provider, entry.Model)\n\t\t}\n\t\tif verified.After(time.Now().UTC().Add(24 * time.Hour)) {\n\t\t\treturn nil, fmt.Errorf(\"%s %s/%s: verified_at is in the future\", label, entry.Provider, entry.Model)\n\t\t}\n\t\tif entry.CapabilitiesVerifiedAt != \"\" {\n\t\t\tcapVerified, err := time.Parse(time.RFC3339, entry.CapabilitiesVerifiedAt)\n\t\t\tif err != nil || capVerified.IsZero() {\n\t\t\t\treturn nil, fmt.Errorf(\"%s %s/%s: capabilities_verified_at must be RFC3339\", label, entry.Provider, entry.Model)","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/shared/platform/catalog/catalog.go#L246-L282","documentation":"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.","triggerScenarios":"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').","commonSituations":"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.","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."],"exampleFix":"# before\n- provider: anthropic\n  model: claude-sonnet-4\n  region: \"\"\n\n# after\n- provider: anthropic\n  model: claude-sonnet-4\n  region: us","handlingStrategy":"validation","validationCode":"func validCatalogEntry(e Entry) bool {\n    return strings.TrimSpace(e.Provider) != \"\" &&\n        strings.TrimSpace(e.Model) != \"\" &&\n        strings.TrimSpace(e.Region) != \"\"\n}","typeGuard":null,"tryCatchPattern":"Catch catalog load errors at startup and fail fast with the file path + entry index; do not run with a partial catalog.","preventionTips":["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."],"tags":["catalog","yaml","pricing","validation"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}