{"record":{"id":"53e7ec0bebbacc2f","repo":"JuliusBrussee/caveman","slug":"kms-create-s-request-w","errorCode":null,"errorMessage":"kms: create %s request: %w","messagePattern":"kms: create (.+?) request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/kms/kms.go","lineNumber":355,"sourceCode":"\tif !regionPattern.MatchString(region) {\n\t\treturn errors.New(\"kms: invalid Scaleway region\")\n\t}\n\tif !keyIDPattern.MatchString(keyID) {\n\t\treturn errors.New(\"kms: invalid Scaleway key ID\")\n\t}\n\treturn nil\n}\n\nfunc (c *Client) call(ctx context.Context, region, keyID, operation string, input, output any) error {\n\tbody, err := json.Marshal(input)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"kms: encode %s request: %w\", operation, err)\n\t}\n\tendpoint := c.apiBaseURL + \"/key-manager/v1alpha1/regions/\" + url.PathEscape(region) +\n\t\t\"/keys/\" + url.PathEscape(keyID) + \"/\" + operation\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"kms: create %s request: %w\", operation, err)\n\t}\n\treq.Header.Set(\"content-type\", \"application/json\")\n\treq.Header.Set(\"accept\", \"application/json\")\n\treq.Header.Set(\"x-auth-token\", c.token)\n\tresp, err := c.httpClient.Do(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"kms: %s request failed: %w\", operation, err)\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\t_, _ = io.Copy(io.Discard, io.LimitReader(resp.Body, 32<<10))\n\t\treturn fmt.Errorf(\"kms: %s returned HTTP %d\", operation, resp.StatusCode)\n\t}\n\tdata, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseBytes+1))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"kms: read %s response: %w\", operation, err)\n\t}\n\tif len(data) > maxResponseBytes {","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/kms/kms.go#L337-L373","documentation":"call builds the Key Manager endpoint URL and creates the request with http.NewRequestWithContext; if request construction fails, the error is wrapped as \"kms: create <operation> request: %w\". NewRequestWithContext only fails on an unparseable URL or an invalid method, so this points to a malformed apiBaseURL in the client configuration.","triggerScenarios":"Calling Encrypt or Decrypt when c.apiBaseURL is empty, contains spaces/control characters, or is otherwise unparseable, making the concatenation an invalid URL; the operation path component itself is escaped, so the base URL is the usual culprit.","commonSituations":"Configuring apiBaseURL from an env var with a trailing newline or whitespace; missing scheme (e.g. \"scaleway.api\" instead of \"https://...\"); config templating leaving a placeholder like \"{{API_URL}}\" unexpanded.","solutions":["Inspect and fix the apiBaseURL used at construction — it must be an absolute, valid URL like https://api.scaleway.com.","Trim/expand the env var or config value feeding apiBaseURL (no newlines, no unexpanded templates).","Validate the URL with url.Parse before constructing the client and fail fast on bad config.","Unwrap the error chain for the exact url.Parse failure message."],"exampleFix":"// before\nclient := &kms.Client{apiBaseURL: os.Getenv(\"SCW_API\"), ...} // SCW_API=\"\"\n_, err := client.Encrypt(ctx, pt) // kms: create encrypt request: ...\n// after\nbase := strings.TrimSpace(os.Getenv(\"SCW_API\"))\nif u, err := url.Parse(base); err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid SCW_API base URL %q\", base)\n}\nclient := &kms.Client{apiBaseURL: base, ...}","handlingStrategy":"validation","validationCode":"base := strings.TrimSpace(cfg.APIBaseURL)\nif u, err := url.Parse(base); err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"apiBaseURL %q is not an absolute URL\", base)\n}","typeGuard":"func validBaseURL(s string) bool {\n    u, err := url.Parse(s)\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\"\n}","tryCatchPattern":"_, err := client.Encrypt(ctx, plaintext)\nif err != nil {\n    if strings.Contains(err.Error(), \"create encrypt request\") {\n        return fmt.Errorf(\"malformed KMS endpoint config: %w\", err)\n    }\n    return err\n}","preventionTips":["Validate apiBaseURL with url.Parse at client construction.","Trim env/config values feeding the base URL (strip whitespace/newlines).","Fail startup fast if the templated URL still contains placeholders.","Only use https:// absolute URLs for the Key Manager endpoint."],"tags":["go","kms","http","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"}