{"record":{"id":"fc7a4f6f54a0c53f","repo":"JuliusBrussee/caveman","slug":"envelope-unwrap-data-key-w","errorCode":null,"errorMessage":"envelope: unwrap data key: %w","messagePattern":"envelope: unwrap data key: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/envelope/envelope.go","lineNumber":146,"sourceCode":"\t}\n\taad, scopeHash, err := scopeAAD(scope)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif meta.ScopeHash != scopeHash {\n\t\treturn nil, fmt.Errorf(\"envelope: tenant scope mismatch\")\n\t}\n\treturn open(ciphertext, meta, aad)\n}\n\nfunc open(ciphertext []byte, meta Metadata, aad []byte) ([]byte, error) {\n\twrapped, err := base64.StdEncoding.DecodeString(meta.WrappedDataKey)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"envelope: decode wrapped key: %w\", err)\n\t}\n\tdataKey, err := secretbox.DecryptPayloadKey(wrapped)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"envelope: unwrap data key: %w\", err)\n\t}\n\tblock, err := aes.NewCipher(dataKey)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"envelope: aes: %w\", err)\n\t}\n\tgcm, err := cipher.NewGCM(block)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"envelope: gcm: %w\", err)\n\t}\n\tns := gcm.NonceSize()\n\tif len(ciphertext) < ns {\n\t\treturn nil, fmt.Errorf(\"envelope: ciphertext too short\")\n\t}\n\tnonce, ct := ciphertext[:ns], ciphertext[ns:]\n\tplaintext, err := gcm.Open(nil, nonce, ct, aad)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"envelope: open: %w\", err)\n\t}","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/766dce6b1394ebb56a3090748d5a0240a5aefb36/shared/platform/envelope/envelope.go#L128-L164","documentation":"Fires in open() when secretbox.DecryptPayloadKey cannot unwrap the base64-decoded WrappedDataKey from the envelope Metadata — i.e. the wrapped key blob is corrupt, truncated, tampered with, or was produced by a different key-encryption key. This happens before any payload decryption, so the failure is about the key layer, not the ciphertext itself.","triggerScenarios":"Thrown at shared/platform/envelope/envelope.go:146 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Verify the record's Metadata (WrappedDataKey) was not truncated or altered in storage; re-seal the payload if the metadata is corrupt","Confirm the KMS/master key used to wrap data keys has not been rotated or deleted since sealing","Ensure base64 decoding succeeded for the right field and no whitespace or padding was stripped in transit"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"766dce6b1394ebb56a3090748d5a0240a5aefb36","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}