{"record":{"id":"beb64bf2c6c0dd71","repo":"JuliusBrussee/caveman","slug":"kms-probe-decrypt-w","errorCode":null,"errorMessage":"kms: probe decrypt: %w","messagePattern":"kms: probe decrypt: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/kms/kms.go","lineNumber":328,"sourceCode":"\tif err != nil {\n\t\treturn err\n\t}\n\treturn client.Probe(ctx)\n}\n\n// Probe verifies live key access without persisting tenant data.\nfunc (c *Client) Probe(ctx context.Context) error {\n\tplaintext := make([]byte, 32)\n\tif _, err := rand.Read(plaintext); err != nil {\n\t\treturn fmt.Errorf(\"kms: generate probe: %w\", err)\n\t}\n\tenvelope, err := c.Encrypt(ctx, plaintext)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"kms: probe encrypt: %w\", err)\n\t}\n\tdecrypted, err := c.Decrypt(ctx, envelope)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"kms: probe decrypt: %w\", err)\n\t}\n\tif !bytes.Equal(decrypted, plaintext) {\n\t\treturn errors.New(\"kms: probe plaintext mismatch\")\n\t}\n\treturn nil\n}\n\nfunc validateLocation(region, keyID string) error {\n\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 {","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/kms/kms.go#L310-L346","documentation":"Probe completes its round trip by Decrypting the envelope it just encrypted; any Decrypt failure is re-wrapped as \"kms: probe decrypt: %w\". A failure here means the key cannot decrypt data it just encrypted — usually an API, permission, or envelope-validation problem on the decrypt path.","triggerScenarios":"Calling Probe when the inner Decrypt fails: envelope size limit, JSON decode failure, provider mismatch, validateLocation rejecting the envelope's region/keyID, or decrypt API/network errors via client.call.","commonSituations":"Key rotation removing the key between the two calls; per-operation IAM (encrypt allowed, decrypt denied); envelope byte corruption in transport within the probe; region mismatch between client config and API response.","solutions":["Unwrap the error chain to find which Decrypt validation failed (provider, location, API, or network).","Check IAM/key policy grants decrypt (not just encrypt) for the token in use.","Confirm no key deletion/rotation raced between the Encrypt and Decrypt inside Probe.","Verify client region/keyID match where the key actually lives; re-Probe after fixes."],"exampleFix":"// before\nerr := client.Probe(ctx) // kms: probe decrypt: kms: envelope provider does not match...\n// after\nif err := client.Probe(ctx); err != nil {\n    if strings.Contains(err.Error(), \"probe decrypt\") {\n        log.Println(\"decrypt path broken: check decrypt IAM grants and key state\")\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"if err := client.Probe(ctx); err != nil && strings.Contains(err.Error(), \"probe decrypt\") {\n    return errors.New(\"decrypt path broken: verify key grants include decrypt\")\n}","typeGuard":null,"tryCatchPattern":"if err := client.Probe(ctx); err != nil {\n    switch {\n    case strings.Contains(err.Error(), \"probe encrypt\"):\n        log.Println(\"KMS write path failing\")\n    case strings.Contains(err.Error(), \"probe decrypt\"):\n        log.Println(\"KMS read path failing: check decrypt IAM grants\")\n    }\n    return err\n}","preventionTips":["Grant both encrypt and decrypt permissions on the key.","Beware key rotation/deletion racing with encrypt-then-decrypt flows.","Run Probe in CI against staging keys to catch policy drift.","Unwrap the error chain to see which Decrypt validation failed."],"tags":["go","kms","probe","decryption","api"],"backgroundTag":"upstream-api-error","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"}