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 working

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Add at least one source URL under the entry (e.g. the vendor pricing page you verified).
  2. Note each URL must also be an absolute HTTPS URL or you'll hit the follow-on 'invalid HTTPS source' error.
  3. 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

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


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/e72c1f84ef9bd820. Report an issue: GitHub.