{"record":{"id":"ec1803e7b7f5c002","repo":"oauth2-proxy/oauth2-proxy","slug":"could-not-parse-s-url-v","errorCode":null,"errorMessage":"could not parse %s URL: %v","messagePattern":"could not parse (.+?) URL: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"providers/providers.go","lineNumber":138,"sourceCode":"\t\t\tp.SupportedCodeChallengeMethods = pkce.CodeChallengeAlgs\n\t\t}\n\t}\n\n\terrs := []error{}\n\tfor name, u := range map[string]struct {\n\t\tdst **url.URL\n\t\traw string\n\t}{\n\t\t\"login\":    {dst: &p.LoginURL, raw: providerConfig.LoginURL},\n\t\t\"redeem\":   {dst: &p.RedeemURL, raw: providerConfig.RedeemURL},\n\t\t\"profile\":  {dst: &p.ProfileURL, raw: providerConfig.ProfileURL},\n\t\t\"validate\": {dst: &p.ValidateURL, raw: providerConfig.ValidateURL},\n\t\t\"resource\": {dst: &p.ProtectedResource, raw: providerConfig.ProtectedResource},\n\t} {\n\t\tvar err error\n\t\t*u.dst, err = url.Parse(u.raw)\n\t\tif err != nil {\n\t\t\terrs = append(errs, fmt.Errorf(\"could not parse %s URL: %v\", name, err))\n\t\t}\n\t}\n\t// handle LoginURLParameters\n\terrs = append(errs, p.compileLoginParams(providerConfig.LoginURLParameters)...)\n\n\tif len(errs) > 0 {\n\t\treturn nil, k8serrors.NewAggregate(errs)\n\t}\n\n\t// Make the OIDC options available to all providers that support it\n\tp.AllowUnverifiedEmail = ptr.Deref(providerConfig.OIDCConfig.InsecureAllowUnverifiedEmail, options.DefaultInsecureAllowUnverifiedEmail)\n\tp.EmailClaim = providerConfig.OIDCConfig.EmailClaim\n\tp.GroupsClaim = providerConfig.OIDCConfig.GroupsClaim\n\tp.SkipClaimsFromProfileURL = ptr.Deref(providerConfig.SkipClaimsFromProfileURL, options.DefaultSkipClaimsFromProfileURL)\n\n\t// Set PKCE enabled or disabled based on discovery and force options\n\tp.CodeChallengeMethod = parseCodeChallengeMethod(providerConfig)\n\tif len(p.SupportedCodeChallengeMethods) != 0 && p.CodeChallengeMethod == \"\" {","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/oauth2-proxy/oauth2-proxy/blob/33c2eb92dea78204f7a18bc2dfdbccc220f39257/providers/providers.go#L120-L156","documentation":"newProviderDataFromConfig parses each provider URL field (RedeemURL, LoginURL, ProfileURL, ValidateURL, ProtectedResource, etc.) with net/url.Parse and accumulates failures as \"could not parse %s URL: %v\". It signals a provider option URL string is not a valid absolute URL. All failures are collected and returned together.","triggerScenarios":"Any provider config where providerConfig.RedeemURL / LoginURL / ProfileURL / ValidateURL / ProtectedResource (or the specific field named in the message) fails url.Parse — e.g. contains spaces, control characters, a bare hostname without scheme is actually parseable but malformed ones like \"http://exa mple.com\" or \"::bad::\" fail.","commonSituations":"Copy-pasted URLs with trailing spaces or newlines from YAML; unescaped special characters (|, # misuse) in flags; template/secret placeholders left unexpanded (e.g. \"${REDEEM_URL}\"); shell quoting issues when passing URLs as CLI flags.","solutions":["Identify which URL field failed from the %s name in the message and inspect the raw configured value for spaces/newlines/control chars.","Trim whitespace and ensure the value is a well-formed URL with scheme, e.g. https://provider.example.com/oauth/redeem.","If the value comes from a flag/env/file, verify the env var is expanded (no literal ${VAR} left) and shell quoting is correct.","Validate URLs before deployment with a quick Go/python url-parse check or by running oauth2-proxy with --provider debug startup."],"exampleFix":"// before\nredeemURL: \"https://sso.example.com/oauth/redeem\\n\"\n// after\nredeemURL: \"https://sso.example.com/oauth/redeem\"","handlingStrategy":"validation","validationCode":"for name, raw := range map[string]string{\"redeem\": redeemURL, \"login\": loginURL, \"profile\": profileURL, \"validate\": validateURL} {\n    if _, err := url.Parse(strings.TrimSpace(raw)); err != nil {\n        return fmt.Errorf(\"provider %s URL invalid: %v\", name, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if _, err := url.Parse(raw); err != nil {\n    return fmt.Errorf(\"invalid %s URL %q: %w\", name, raw, err)\n}","preventionTips":["Trim all URL config values loaded from YAML/env files.","Quote URLs in shell/CLI flags to avoid stray characters.","Verify secret/template placeholders ($VAR, ${VAR}) are actually expanded before startup.","Add a config-lint step that url.Parse's every provider URL."],"tags":["url","config","validation"],"backgroundTag":"invalid-url","analyzedSha":"33c2eb92dea78204f7a18bc2dfdbccc220f39257","analyzedAt":"2026-09-06T08:51:53.077Z","contentChangedAt":"2026-09-06T08:51:53.077Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}