{"record":{"id":"91efa99b8e10c4bf","repo":"JuliusBrussee/caveman","slug":"kms-invalid-api-base-url","errorCode":null,"errorMessage":"kms: invalid API base URL","messagePattern":"kms: invalid API base URL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/kms/kms.go","lineNumber":102,"sourceCode":"\tdecryptKeyIDs := map[string]struct{}{keyID: {}}\n\tfor _, allowedKeyID := range cfg.AllowedDecryptKeyIDs {\n\t\tallowedKeyID = strings.TrimSpace(allowedKeyID)\n\t\tif err := validateLocation(region, allowedKeyID); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdecryptKeyIDs[allowedKeyID] = struct{}{}\n\t}\n\ttoken := strings.TrimSpace(cfg.AuthToken)\n\tif len(token) < 20 {\n\t\treturn nil, errors.New(\"kms: auth token is required\")\n\t}\n\tbaseURL := strings.TrimRight(strings.TrimSpace(cfg.APIBaseURL), \"/\")\n\tif baseURL == \"\" {\n\t\tbaseURL = scalewayAPI\n\t}\n\tparsed, err := url.Parse(baseURL)\n\tif err != nil || parsed.Scheme == \"\" || parsed.Host == \"\" || parsed.User != nil || parsed.RawQuery != \"\" || parsed.Fragment != \"\" {\n\t\treturn nil, errors.New(\"kms: invalid API base URL\")\n\t}\n\tclient := cfg.HTTPClient\n\tif client == nil {\n\t\tclient = &http.Client{\n\t\t\tTimeout: 8 * time.Second,\n\t\t\tCheckRedirect: func(_ *http.Request, _ []*http.Request) error {\n\t\t\t\treturn http.ErrUseLastResponse\n\t\t\t},\n\t\t}\n\t}\n\treturn &Client{provider: provider, region: region, keyID: keyID, token: token, apiBaseURL: baseURL, httpClient: client, decryptKeyIDs: decryptKeyIDs}, nil\n}\n\n// FromEnvironment loads production configuration. Endpoint is not configurable,\n// preventing env-driven host redirection of KMS credentials.\nfunc FromEnvironment() (*Client, error) {\n\treturn fromEnvironment(SecretsKeyEnvironment)\n}","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/kms/kms.go#L84-L120","documentation":"New parses the configured Scaleway KMS API base URL and rejects any URL that fails url.Parse, lacks a scheme or host, or carries userinfo, a query string, or a fragment. Only clean absolute http(s) base URLs are accepted.","triggerScenarios":"Passing Config.APIBaseURL set to something like \"localhost:8080\" (no scheme), \"https://api.example.com/path?x=1\" (query), \"https://user:pass@host\" (userinfo), or a URL with \"#fragment\".","commonSituations":"Pointing the client at a local mock server with a scheme-less URL, appending query params for debugging, proxy configuration mistakes, or typos in the override base URL.","solutions":["Include the scheme: use \"https://...\" (or \"http://\" only for local testing)","Remove any query string, fragment, and user info from the base URL","If overriding for tests, use e.g. httptest server URL as-is: srv.URL already includes the scheme and host"],"exampleFix":"// before\ncfg := kms.Config{APIBaseURL: \"api.scaleway.com?debug=1\"}\n// after\ncfg := kms.Config{APIBaseURL: \"https://api.scaleway.com\"}","handlingStrategy":"validation","validationCode":"u, err := url.Parse(cfg.APIBaseURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" || u.User != nil || u.RawQuery != \"\" || u.Fragment != \"\" {\n\treturn fmt.Errorf(\"invalid APIBaseURL: %q\", cfg.APIBaseURL)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include scheme and host in base URLs","Never append query strings or credentials to a base URL","For tests, use httptest.NewServer(...).URL directly"],"tags":["kms","url","config"],"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"}