JuliusBrussee/caveman · error · CatalogError
: missing field(s)
Error message
{label}: missing field(s): {', '.join(sorted(missing))} What it means
A required top-level field is absent from a catalog row. Every row must carry provider, model, region, currency, pricing, capabilities, sources, and verified_at (capabilities_verified_at is optional); a missing key means the row cannot be identified, priced, or snapshot-pinned. Thrown from validate_row.
Solutions
- Add the listed missing field(s) to the row, copying structure from a neighboring valid row
- For pricing fields that don't apply, include them inside `pricing` as explicit null rather than omitting row-level keys
- If a sync script produced the row, fix its template to emit all required keys
- Run the validator again — it reports all missing fields for the row at once
Example fix
# before
- provider: openai
model: gpt-4o
region: global
# after
- provider: openai
model: gpt-4o
region: global
currency: USD
pricing: {input_per_million: 2.5, output_per_million: 10.0}
capabilities: {}
sources: ["https://openai.com/pricing"]
verified_at: "2026-07-05T00:00:00Z" Defensive patterns
Strategy: validation
Validate before calling
REQUIRED_KEYS = {"provider","model","region","currency","pricing","capabilities","sources","verified_at"}
def all_required_present(row: dict) -> bool:
return not (REQUIRED_KEYS - set(row)) Type guard
def is_complete_row(row: object) -> bool:
return isinstance(row, dict) and REQUIRED_KEYS.issubset(row) Try / catch
try:
validate_catalog()
except CatalogError as e:
if "missing field(s)" in str(e):
fill_missing_fields(str(e)) Prevention
- Start new rows from a copy of an existing complete row
- Run the validator locally before every catalog commit
- Keep sync-script row templates in sync with REQUIRED_KEYS
When it happens
Trigger: validate_row computes `REQUIRED_KEYS - set(row)` non-empty, e.g. a newly added row forgetting `sources`, a snapshot row copied without `verified_at`, or a bulk edit deleting a key. The message lists exactly which fields are missing.
Common situations: Adding a new model row by hand and forgetting one of the eight fields; a sync script emitting partial rows; deleting a field during a merge-conflict resolution; copying a row template that predates a required field.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- : unknown field(s)
- : unknown pricing field(s)
- : every catalog row must be an object
- catalog is empty
- catalog
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/236ece813cc5a956.
Report an issue: GitHub.
Appendix: source
Thrown at shared/provider-catalog/validate_catalog.py:122
elif isinstance(value, str):
try:
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
except ValueError as error:
raise CatalogError(f"{label}: verified_at must be RFC3339") from error
else:
raise CatalogError(f"{label}: verified_at must be an RFC3339 timestamp")
if parsed.tzinfo is None:
raise CatalogError(f"{label}: verified_at must include a timezone")
return parsed.astimezone(timezone.utc)
def validate_row(row: dict[str, Any], label: str, now: datetime) -> tuple[str, str, str]:
unknown = set(row) - TOP_LEVEL_KEYS
missing = REQUIRED_KEYS - set(row)
if unknown:
raise CatalogError(f"{label}: unknown field(s): {', '.join(sorted(unknown))}")
if missing:
raise CatalogError(f"{label}: missing field(s): {', '.join(sorted(missing))}")
identity: list[str] = []
for field in ("provider", "model", "region"):
value = row[field]
if not isinstance(value, str) or not IDENTIFIER.fullmatch(value):
raise CatalogError(f"{label}: {field} must be a safe non-empty identifier")
identity.append(value)
if row["currency"] != "USD":
raise CatalogError(f"{label}: currency must be USD")
pricing = row["pricing"]
if not isinstance(pricing, dict):
raise CatalogError(f"{label}: pricing must be an object")
pricing_unknown = set(pricing) - PRICING_KEYS
if pricing_unknown:
raise CatalogError(f"{label}: unknown pricing field(s): {', '.join(sorted(pricing_unknown))}")
for required in ("input_per_million", "output_per_million"):
if required not in pricing:View on GitHub (pinned to 3ee70a1026)