mongodb/node-mongodb-native · error · MongoInvalidArgumentError
input cluster time must have a valid "signature" property…
Error message
input cluster time must have a valid "signature" property with BSON Binary hash and BSON Long keyId
What it means
`advanceClusterTime` validates the `signature` field: it must exist, `signature.hash` must be a BSON Binary, and `signature.keyId` must be a bigint, number, or BSON Long. Any deviation throws MongoInvalidArgumentError. The check exists because the server signs cluster times and an invalid signature would corrupt auth/cluster-time gossip.
Solutions
- Forward the server's `$clusterTime` document intact, including its `signature`.
- Use BSON encode/decode for cross-process transport so Binary and Long survive.
- When reconstructing, build `Long`/`Binary` instances: `new Long(keyIdLow, keyIdHigh)` and `new Binary(buffer, subtype)`.
Example fix
// before (after JSON round-trip — signature lost BSON types)
session.advanceClusterTime(jsonParsedClusterTime);
// after
import { deserialize } from 'mongodb';
const ct = deserialize(serialisedBuffer);
session.advanceClusterTime(ct.$clusterTime); Defensive patterns
Strategy: type-guard
Validate before calling
function hasValidSignature(ct) {
const sig = ct?.signature;
return sig?.hash?._bsontype === 'Binary' &&
(typeof sig?.keyId === 'bigint' || typeof sig?.keyId === 'number' || sig?.keyId?._bsontype === 'Long');
}
if (hasValidSignature(ct)) session.advanceClusterTime(ct); Type guard
function isValidSignedClusterTime(v) {
if (!v || typeof v !== 'object') return false;
if (v.clusterTime?._bsontype !== 'Timestamp') return false;
const sig = v.signature;
return sig?.hash?._bsontype === 'Binary' &&
(typeof sig?.keyId === 'bigint' || typeof sig?.keyId === 'number' || sig?.keyId?._bsontype === 'Long');
} Prevention
- Transport cluster time via BSON so Binary and Long survive.
- Forward the whole `$clusterTime` document from the server unchanged.
- Reconstruct missing BSON types explicitly when rebuilding docs.
When it happens
Trigger: Forwarding a cluster time with a missing or wrong-typed signature; reconstructing the doc after JSON round-trip (Long becomes object, Binary becomes base64 string); stripping signature intentionally for test purposes.
Common situations: Cross-process cluster-time propagation that did not preserve BSON types; test doubles that build cluster time without real signature data; bug in a serialisation layer.
Related errors
- input cluster time "clusterTime" property must be a valid…
- input cluster time must be an object
- Cannot call abortTransaction after calling commitTransaction
- Cannot call abortTransaction twice
- Cannot call commitTransaction after calling abortTransaction
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/b20c3488273c3d99.
Report an issue: GitHub.
Appendix: source
Thrown at src/sessions.ts:336
* @param clusterTime - the $clusterTime returned by the server from another session in the form of a document containing the `BSON.Timestamp` clusterTime and signature
*/
advanceClusterTime(clusterTime: ClusterTime): void {
if (!clusterTime || typeof clusterTime !== 'object') {
throw new MongoInvalidArgumentError('input cluster time must be an object');
}
if (!clusterTime.clusterTime || clusterTime.clusterTime._bsontype !== 'Timestamp') {
throw new MongoInvalidArgumentError(
'input cluster time "clusterTime" property must be a valid BSON Timestamp'
);
}
if (
!clusterTime.signature ||
clusterTime.signature.hash?._bsontype !== 'Binary' ||
(typeof clusterTime.signature.keyId !== 'bigint' &&
typeof clusterTime.signature.keyId !== 'number' &&
clusterTime.signature.keyId?._bsontype !== 'Long') // apparently we decode the key to number?
) {
throw new MongoInvalidArgumentError(
'input cluster time must have a valid "signature" property with BSON Binary hash and BSON Long keyId'
);
}
_advanceClusterTime(this, clusterTime);
}
/**
* Used to determine if this session equals another
*
* @param session - The session to compare to
*/
equals(session: ClientSession): boolean {
if (!(session instanceof ClientSession)) {
return false;
}
if (this.id == null || session.id == null) {View on GitHub (pinned to dce7939f86)