{"record":{"id":"2960251a9396570e","repo":"mongodb/node-mongodb-native","slug":"finalization-error","errorCode":null,"errorMessage":"Finalization error","messagePattern":"Finalization error","errorType":"exception","errorClass":"MongoCryptError","httpStatus":null,"severity":"critical","filePath":"src/client-side-encryption/state_machine.ts","lineNumber":273,"sourceCode":"        }\n\n        case MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: {\n          const kmsProviders = await executor.askForKMSCredentials();\n          context.provideKMSProviders(serialize(kmsProviders));\n          break;\n        }\n\n        case MONGOCRYPT_CTX_NEED_KMS: {\n          await Promise.all(this.requests(context, options));\n          context.finishKMSRequests();\n          break;\n        }\n\n        case MONGOCRYPT_CTX_READY: {\n          const finalizedContext = context.finalize();\n          if (getState() === MONGOCRYPT_CTX_ERROR) {\n            const message = getStatus().message || 'Finalization error';\n            throw new MongoCryptError(message);\n          }\n          result = finalizedContext;\n          break;\n        }\n\n        default:\n          throw new MongoCryptError(`Unknown state: ${getState()}`);\n      }\n    }\n\n    if (getState() === MONGOCRYPT_CTX_ERROR || result == null) {\n      const message = getStatus().message;\n      if (!message) {\n        debug(\n          `unidentifiable error in MongoCrypt - received an error status from \\`libmongocrypt\\` but received no error message.`\n        );\n      }\n      throw new MongoCryptError(","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/client-side-encryption/state_machine.ts#L255-L291","documentation":"Fallback message in the CSFLE state machine's MONGOCRYPT_CTX_READY branch: libmongocrypt's context.finalize() left the state in ERROR but context.status.message was empty, so the driver uses 'Finalization error'. Finalization is where the encrypted/decrypted bytes are produced; an error here usually means the crypto operation itself failed (bad key, bad algorithm, malformed ciphertext).","triggerScenarios":"Decrypting a value whose data key is missing or was created with a different KMS/CMK; encrypting with an algorithm/key combination libmongocrypt rejects; corrupted ciphertext; finalize of a context that was fed inconsistent data.","commonSituations":"Data key was deleted or rotated and old ciphertext can't be unwrapped; CMK in the KMS was disabled/rotated; algorithm mismatch between encrypt and decrypt (e.g. Random vs Deterministic); range/queryable-encryption options incompatible with the key material.","solutions":["Ensure the data encryption key (DEK) referenced by keyId/keyAltName still exists in the key vault collection and can be unwrapped by the configured KMS.","Confirm the CMK in the KMS (AWS/Azure/GCP/local) is enabled and that the credentials have wrap/unwrap permission.","Match the encryption algorithm exactly between encrypt and decrypt; for Queryable Encryption, ensure queryType/contentionFactor/rangeOptions match what was used to encrypt.","Re-create the DEK if the CMK was rotated and the old key material is gone, then re-encrypt affected data."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await clientEncryption.decrypt(value);\n} catch (e) {\n  if (e instanceof MongoCryptError && /Finalization error/i.test(e.message)) {\n    // verify the DEK exists and the CMK is enabled, then re-encrypt/retry\n  }\n  throw e;\n}","preventionTips":["Never delete data encryption keys while ciphertext referencing them still exists; back them up.","Keep algorithm and queryType consistent across encrypt/decrypt for a given field."],"tags":["csfle","client-side-encryption","crypto","kms"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}