JuliusBrussee/caveman · error
%s %s/%s: at least one source is required
Error message
%s %s/%s: at least one source is required
What it means
Thrown by the catalog YAML loader when an entry carries an empty sources list. Every pricing row must cite at least one source URL so numbers are auditable; rows without provenance are rejected at load.
Source
Thrown at shared/platform/catalog/catalog.go:289
}
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)
}
if capVerified.After(time.Now().UTC().Add(24 * time.Hour)) {
return nil, fmt.Errorf("%s %s/%s: capabilities_verified_at is in the future", label, entry.Provider, entry.Model)
}
}
if len(entry.Sources) == 0 {
return nil, fmt.Errorf("%s %s/%s: at least one source is required", label, entry.Provider, entry.Model)
}
for _, rawURL := range entry.Sources {
u, err := url.ParseRequestURI(rawURL)
if err != nil || u.Scheme != "https" || u.Host == "" {
return nil, fmt.Errorf("%s %s/%s: invalid HTTPS source %q", label, entry.Provider, entry.Model, rawURL)
}
}
key := entry.Provider + "\x00" + entry.Model + "\x00" + entry.Region
if _, duplicate := seen[key]; duplicate {
return nil, fmt.Errorf("duplicate provider/model/region row %s/%s@%s", entry.Provider, entry.Model, entry.Region)
}
seen[key] = struct{}{}
}
return decoded, nil
}
// catalogCandidates lists the paths to try, in order: an explicit env override,
// the deploy-image and CWD-relative locations, then a walk up from the workingView on GitHub (pinned to 27d5a3981a)
Solutions
- Add at least one source URL under the entry (e.g. the vendor pricing page you verified).
- Note each URL must also be an absolute HTTPS URL or you'll hit the follow-on 'invalid HTTPS source' error.
- If re-verifying, record the page you actually used at verification time and update verified_at accordingly.
Example fix
# before sources: [] # after sources: - https://docs.anthropic.com/en/docs/about-claude/pricing
Defensive patterns
Strategy: validation
Validate before calling
if len(entry.Sources) == 0 {
return fmt.Errorf("entry %d %s/%s: add at least one HTTPS source URL", i, entry.Provider, entry.Model)
} Try / catch
Fail catalog load at startup; provenance is mandatory and cannot be defaulted.
Prevention
- Capture the pricing-page URL at the moment you verify prices.
- Add the source in the same edit that adds or updates a price.
- CI-load the catalog so source-less rows cannot merge.
When it happens
Trigger: An entry with sources: [] or with the sources key omitted — len(entry.Sources) == 0 fails the check before individual URL validation runs.
Common situations: Adding a new model quickly without gathering the pricing page URL; a generator that only emits sources conditionally; deleting a dead link row entirely instead of replacing it.
Related errors
- %s %s/%s: invalid HTTPS source %q
- ${label}:${lineNo}: "${text}" is not a finite number
- ${label}: row is missing a string "${field}"
- ${label}: ${key} has no pricing block
- {label}: dropped or replaced a source from its immutable sna
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/e72c1f84ef9bd820.
Report an issue: GitHub.