{"record":{"id":"04164ecae154fdf9","repo":"JuliusBrussee/caveman","slug":"s-s-s-invalid-https-source-q","errorCode":null,"errorMessage":"%s %s/%s: invalid HTTPS source %q","messagePattern":"(.+?) (.+?)/(.+?): invalid HTTPS source %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/catalog/catalog.go","lineNumber":294,"sourceCode":"\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)\n\t\t\t}\n\t\t\tif capVerified.After(time.Now().UTC().Add(24 * time.Hour)) {\n\t\t\t\treturn nil, fmt.Errorf(\"%s %s/%s: capabilities_verified_at is in the future\", label, entry.Provider, entry.Model)\n\t\t\t}\n\t\t}\n\t\tif len(entry.Sources) == 0 {\n\t\t\treturn nil, fmt.Errorf(\"%s %s/%s: at least one source is required\", label, entry.Provider, entry.Model)\n\t\t}\n\t\tfor _, rawURL := range entry.Sources {\n\t\t\tu, err := url.ParseRequestURI(rawURL)\n\t\t\tif err != nil || u.Scheme != \"https\" || u.Host == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"%s %s/%s: invalid HTTPS source %q\", label, entry.Provider, entry.Model, rawURL)\n\t\t\t}\n\t\t}\n\t\tkey := entry.Provider + \"\\x00\" + entry.Model + \"\\x00\" + entry.Region\n\t\tif _, duplicate := seen[key]; duplicate {\n\t\t\treturn nil, fmt.Errorf(\"duplicate provider/model/region row %s/%s@%s\", entry.Provider, entry.Model, entry.Region)\n\t\t}\n\t\tseen[key] = struct{}{}\n\t}\n\treturn decoded, nil\n}\n\n// catalogCandidates lists the paths to try, in order: an explicit env override,\n// the deploy-image and CWD-relative locations, then a walk up from the working\n// directory so the catalog resolves when binaries or tests run from subdirs.\n// Both repo layouts are tried: the monorepo keeps the catalog under public/,\n// the published caveman repo has it at the top level.\nfunc catalogCandidates() []string {\n\trels := []string{","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/shared/platform/catalog/catalog.go#L276-L312","documentation":"Thrown by the catalog YAML loader when a source entry fails url.ParseRequestURI or is not an absolute https:// URL with a host. Sources are provenance links; HTTP, scheme-less, or malformed URLs are rejected so every citation is a clickable, transport-secure reference.","triggerScenarios":"Source values like \"http://example.com/pricing\" (wrong scheme), \"example.com/pricing\" (no scheme), \"/pricing\" (relative), or strings with characters that fail request-URI parsing; also empty-host URLs like \"https:///pricing\".","commonSituations":"Pasting a bare domain; a source captured as http:// because it was copied from a redirect; trailing prose glued to the URL (\"https://x.com pricing page\").","solutions":["Use the full absolute HTTPS URL: https://host/path.","If the canonical page is http-only, link the https variant of the same page or find the vendor's https pricing page — the catalog does not accept http.","Keep the value a bare URL; put commentary elsewhere."],"exampleFix":"# before\nsources:\n  - example.com/pricing\n  - http://example.com/pricing\n\n# after\nsources:\n  - https://example.com/pricing","handlingStrategy":"validation","validationCode":"func validHTTPSSource(raw string) bool {\n    u, err := url.ParseRequestURI(raw)\n    return err == nil && u.Scheme == \"https\" && u.Host != \"\"\n}","typeGuard":null,"tryCatchPattern":"Fail catalog load at startup naming the offending URL; do not auto-upgrade http:// to https:// (the target must actually serve TLS).","preventionTips":["Copy URLs from the browser address bar on the https page.","Paste URLs as bare values — no quotes, brackets, or trailing text.","Re-check sources when a vendor moves its docs; replace rather than delete dead links."],"tags":["catalog","yaml","url","sources","validation"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}