{"record":{"id":"5abcb9739c468e7f","repo":"JuliusBrussee/caveman","slug":"provider-q-upstream-url-scheme-q-is-not-allowed","errorCode":null,"errorMessage":"provider %q upstream URL scheme %q is not allowed","messagePattern":"provider %q upstream URL scheme %q is not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/providers/openaicompat/openaicompat.go","lineNumber":520,"sourceCode":"\t// a path cannot change route identity after another decoder or proxy hop.\n\tfor _, escape := range []string{\"%2f\", \"%5c\", \"%2e\"} {\n\t\tif strings.Contains(strings.ToLower(path), escape) || strings.Contains(strings.ToLower(rawPath), escape) {\n\t\t\treturn fmt.Errorf(\"ambiguous escaped path sequence %s\", escape)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc parseBaseURL(raw, provider string) (*url.URL, error) {\n\tif strings.TrimSpace(raw) == \"\" {\n\t\treturn nil, fmt.Errorf(\"provider %q has no configured upstream URL\", provider)\n\t}\n\tu, err := url.Parse(strings.TrimSpace(raw))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif u.Scheme != \"http\" && u.Scheme != \"https\" {\n\t\treturn nil, fmt.Errorf(\"provider %q upstream URL scheme %q is not allowed\", provider, u.Scheme)\n\t}\n\tif !u.IsAbs() || u.Host == \"\" || u.Hostname() == \"\" {\n\t\treturn nil, fmt.Errorf(\"provider %q upstream URL must be an absolute URL with a host\", provider)\n\t}\n\tif u.User != nil {\n\t\treturn nil, fmt.Errorf(\"provider %q upstream URL must not include userinfo\", provider)\n\t}\n\tif u.Fragment != \"\" {\n\t\treturn nil, fmt.Errorf(\"provider %q upstream URL must not include a fragment\", provider)\n\t}\n\tif err := validatePathComponents(u.Path, u.RawPath); err != nil {\n\t\treturn nil, fmt.Errorf(\"provider %q upstream URL path rejected: %w\", provider, err)\n\t}\n\treturn u, nil\n}\n","sourceCodeStart":502,"sourceCodeEnd":536,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/proxy/providers/openaicompat/openaicompat.go#L502-L536","documentation":"parseBaseURL enforces that each upstream BaseURL is an absolute http(s) URL with a host, and rejects any other scheme (file:, unix:, ftp:, ws:, etc.). Only http and https are safe to hand to the proxy's HTTP client, so anything else fails validation at config time or request time.","triggerScenarios":"BaseURL like file:///var/run/sock, localhost:8080 (scheme parsed as 'localhost'), ftp://..., or a URL with an unexpected scheme in CAVE_COMPAT_UPSTREAMS / compat: config; values missing the '://' separator entirely.","commonSituations":"Omitting https:// when writing the config (host-only strings); trying to point the upstream at a unix socket via a non-http scheme; copying internal URLs with custom schemes.","solutions":["Prefix the BaseURL with https:// (or http:// for plain-HTTP local upstreams)","Use the form http://127.0.0.1:8080 for local services instead of a bare host:port or unix: scheme","Run the config through ValidateBaseURL at startup to catch bad values before traffic","If you need a unix socket, use a local HTTP proxy that bridges to it rather than a non-http scheme"],"exampleFix":"// before\nBaseURL: \"localhost:8080\"\n\n// after\nBaseURL: \"http://localhost:8080\"","handlingStrategy":"validation","validationCode":"u, err := url.Parse(strings.TrimSpace(raw))\nif err != nil {\n    return err\n}\nif (u.Scheme != \"http\" && u.Scheme != \"https\") || u.Host == \"\" {\n    return fmt.Errorf(\"upstream must be an absolute http(s) URL\")\n}","typeGuard":null,"tryCatchPattern":"if err := ValidateBaseURL(cfg.BaseURL); err != nil {\n    return fmt.Errorf(\"invalid upstream URL for %s: %w\", cfg.Provider, err)\n}","preventionTips":["Always include the scheme (https://) in configured URLs","Run ValidateBaseURL on every upstream entry at startup","Document that only http/https upstreams are supported"],"tags":["go","config","url","validation"],"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"}