mongodb/node-mongodb-native · critical · MongoRuntimeError
Expected result of decryption to be deserialized BSON object
Error message
Expected result of decryption to be deserialized BSON object
What it means
Thrown by decorateDecryptionResult() when, after libmongocrypt returns a decrypted response, that response is still a raw Uint8Array instead of a deserialized BSON object. decorateDecryptionResult walks the decrypted object to mark fields that were encrypted, so it requires an object, not bytes. Hitting this means the CSFLE/Queryable-Encryption decryption pipeline returned bytes where the driver expected an object, typically indicating a version mismatch or a bug in the encryption bindings. It surfaces as a MongoRuntimeError from connection.ts and wire_protocol/responses.ts.
Source
Thrown at src/utils.ts:1358
* Recurse through the (identically-shaped) `decrypted` and `original`
* objects and attach a `decryptedKeys` property on each sub-object that
* contained encrypted fields. Because we only call this on BSON responses,
* we do not need to worry about circular references.
*
* @internal
*/
export function decorateDecryptionResult(
decrypted: Document & { [kDecoratedKeys]?: Array<string> },
original: Document,
isTopLevelDecorateCall = true
): void {
if (isTopLevelDecorateCall) {
// The original value could have been either a JS object or a BSON buffer
if (ByteUtils.isUint8Array(original)) {
original = deserialize(original);
}
if (ByteUtils.isUint8Array(decrypted)) {
throw new MongoRuntimeError('Expected result of decryption to be deserialized BSON object');
}
}
if (!decrypted || typeof decrypted !== 'object') return;
for (const k of Object.keys(decrypted)) {
const originalValue = original[k];
// An object was decrypted by libmongocrypt if and only if it was
// a BSON Binary object with subtype 6.
if (originalValue && originalValue._bsontype === 'Binary' && originalValue.sub_type === 6) {
if (!decrypted[kDecoratedKeys]) {
Object.defineProperty(decrypted, kDecoratedKeys, {
value: [],
configurable: true,
enumerable: false,
writable: false
});
}View on GitHub (pinned to 3366c21a63)
Solutions
- Align versions: use the mongodb-client-encryption (and mongocryptd / crypt_shared) version documented as compatible with your mongodb driver version.
- Rebuild native dependencies (npm rebuild / reinstall) so the libmongocrypt binding compiles and loads correctly.
- Point to a compatible crypt_shared library via the cryptSharedLibPath option, or remove it to use mongocryptd.
- If the issue persists on matched, freshly-built versions, capture the driver + encryption library versions and file a driver bug with the schema and a minimal repro.
Example fix
// before: driver and encryption lib mismatched
const client = new MongoClient(uri, { autoEncryption: { ... } }); // => MongoRuntimeError on first query
// after: pin compatible versions in package.json
// "mongodb": "^6.5.0",
// "mongodb-client-encryption": "^6.0.0"
// then: rm -rf node_modules && npm install Defensive patterns
Strategy: try-catch
Validate before calling
import { MongoClient } from 'mongodb';
function assertEncryptionCompat(driverVer: string, encVer: string): void {
// enforce a known-good combination per the driver's compatibility matrix
const ok = driverVer.startsWith('6.') && encVer.startsWith('6.');
if (!ok) throw new Error(`Unsupported driver/encryption combo: mongodb ${driverVer} + mongodb-client-encryption ${encVer}`);
} Try / catch
try {
await encryptedCollection.findOne(filter);
} catch (err) {
if (err instanceof MongoRuntimeError && /Expected result of decryption to be deserialized BSON/.test(err.message)) {
throw new Error('CSFLE decryption pipeline mismatch; align mongodb and mongodb-client-encryption versions and rebuild natives', { cause: err });
}
throw err;
} Prevention
- Keep mongodb and mongodb-client-encryption on versions documented as compatible.
- Rebuild native modules after node/OS upgrades (npm rebuild).
- Pin a known-good crypt_shared library via cryptSharedLibPath or use mongocryptd explicitly.
- Smoke-test encryption with a trivial insert/find at deploy time to catch mismatch early.
When it happens
Trigger: Running Client-Side Field Level Encryption (CSFLE) or Queryable Encryption where the installed mongodb-client-encryption native binding is incompatible with the driver version; a custom crypt shared library returning an unexpected shape; an internal regression in the decrypt->deserialize ordering.
Common situations: Upgrading the driver without upgrading mongodb-client-encryption (or vice versa); a broken/incomplete native build of libmongocrypt; mismatched crypt_shared library version; environment where the native addon failed to load and fell back to a code path that returns bytes.
Related errors
- "options" cannot contain both "keyId" and "keyAltName"
- "options.keyAltName" must be of type string, but was of type
- No AutoEncrypter available for encryption
- Option "autoEncryption" must be specified
- Auto-encryption requested, but the module is not installed.
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/139c04aa29d566f7.json.
Report an issue: GitHub.