{"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":353,"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":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/catalog/catalog.go#L335-L371","documentation":"DecodeAndValidate validates each entry's source URLs with url.ParseRequestURI and requires https scheme plus a non-empty host. Any http://, ftp://, schemeless, or malformed URL fails closed. This prevents catalog provenance from pointing at insecure or bogus endpoints.","triggerScenarios":"Calling DecodeAndValidate on a catalog entry whose sources contain e.g. \"http://example.com/model\", \"example.com/model\", \"https://\" (no host), or a string with spaces/typos that fails ParseRequestURI.","commonSituations":"Copy-pasting a URL and losing the 's' in https; writing a relative or bare-domain link; trailing whitespace or embedded quotes; an internal doc link that was never a real URL.","solutions":["Change the offending source URL to a fully qualified https:// URL with a hostname.","Strip surrounding whitespace and fix typos in the URL string.","Validate locally with url.ParseRequestURI before committing the catalog.","Re-run DecodeAndValidate to confirm all entries pass."],"exampleFix":"// before\n\"sources\": [\"http://example.com/model-docs\"]\n// after\n\"sources\": [\"https://example.com/model-docs\"]","handlingStrategy":"validation","validationCode":"for _, s := range entry.Sources {\n    u, err := url.ParseRequestURI(strings.TrimSpace(s))\n    if err != nil || u.Scheme != \"https\" || u.Host == \"\" {\n        return fmt.Errorf(\"source %q must be absolute https URL\", s)\n    }\n}","typeGuard":null,"tryCatchPattern":"decoded, err := catalog.DecodeAndValidate(raw, label)\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid HTTPS source\") {\n        return fmt.Errorf(\"fix the cited source URL: %w\", err)\n    }\n    return err\n}","preventionTips":["Copy documentation URLs directly from the browser address bar (always https).","Lint catalog source URLs in CI with the same ParseRequestURI+https check.","Trim whitespace before storing URLs in the catalog."],"tags":["validation","catalog","url","https"],"backgroundTag":"invalid-url-format","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}