{"record":{"id":"eb36db1d98b2948f","repo":"JuliusBrussee/caveman","slug":"kms-unsupported-provider-q","errorCode":null,"errorMessage":"kms: unsupported provider %q","messagePattern":"kms: unsupported provider %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/kms/kms.go","lineNumber":78,"sourceCode":"\ttoken         string\n\tapiBaseURL    string\n\thttpClient    *http.Client\n\tdecryptKeyIDs map[string]struct{}\n}\n\n// Envelope is safe to persist. Ciphertext is opaque provider output.\ntype Envelope struct {\n\tProvider   string `json:\"provider\"`\n\tRegion     string `json:\"region\"`\n\tKeyID      string `json:\"key_id\"`\n\tCiphertext string `json:\"ciphertext\"`\n}\n\n// New validates configuration and returns immutable client.\nfunc New(cfg Config) (*Client, error) {\n\tprovider := strings.ToLower(strings.TrimSpace(cfg.Provider))\n\tif provider != ProviderScaleway {\n\t\treturn nil, fmt.Errorf(\"kms: unsupported provider %q\", provider)\n\t}\n\tregion, keyID := strings.TrimSpace(cfg.Region), strings.TrimSpace(cfg.KeyID)\n\tif err := validateLocation(region, keyID); err != nil {\n\t\treturn nil, err\n\t}\n\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), \"/\")","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/kms/kms.go#L60-L96","documentation":"kms.New only supports the Scaleway provider; any provider value other than ProviderScaleway (case-insensitive, trimmed) is rejected at construction time so the client is always immutable and valid. The returned error names the offending value with %q so config typos are immediately visible.","triggerScenarios":"Calling kms.New(cfg) with cfg.Provider set to \"aws\", \"vault\", \"scw\", \"Scaleway \" with odd casing is fine, but anything not exactly \"scaleway\" after ToLower/TrimSpace throws.","commonSituations":"Copy-pasting KMS config from an AWS/GCP project; an env var like KMS_PROVIDER defaulting to another cloud; typos such as \"scaleway-kms\" or empty provider string.","solutions":["Set cfg.Provider to exactly \"scaleway\" (case/whitespace are normalized).","Check the environment variable or config file feeding cfg.Provider for stale values from another cloud.","If you need another provider, this client does not support it — use that provider's SDK instead."],"exampleFix":"// before\ncfg := kms.Config{Provider: \"aws-kms\", Region: \"fr-par\", KeyID: id}\nclient, err := kms.New(cfg) // kms: unsupported provider \"aws-kms\"\n// after\ncfg := kms.Config{Provider: kms.ProviderScaleway, Region: \"fr-par\", KeyID: id}\nclient, err := kms.New(cfg)","handlingStrategy":"validation","validationCode":"if strings.ToLower(strings.TrimSpace(cfg.Provider)) != \"scaleway\" {\n    return fmt.Errorf(\"provider %q unsupported; only 'scaleway'\", cfg.Provider)\n}\nclient, err := kms.New(cfg)","typeGuard":null,"tryCatchPattern":"client, err := kms.New(cfg)\nif err != nil {\n    if strings.Contains(err.Error(), \"unsupported provider\") {\n        return fmt.Errorf(\"KMS misconfiguration: %w\", err)\n    }\n    return err\n}","preventionTips":["Use the exported kms.ProviderScaleway constant instead of string literals.","Validate provider config at startup, before first use.","Name env vars explicitly (KMS_PROVIDER) and document allowed values.","Add a unit test asserting New fails fast on bad providers."],"tags":["go","kms","config","validation"],"backgroundTag":"unsupported-enum-value","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"}