mongodb/node-mongodb-native · error · MongoInvalidArgumentError
input cluster time must have a valid "signature" property wi
Error message
input cluster time must have a valid "signature" property with BSON Binary hash and BSON Long keyId
What it means
Thrown by ClientSession.advanceClusterTime() when the supplied clusterTime object lacks a well-formed 'signature' property: the signature.hash must be a BSON Binary and signature.keyId must be a bigint, number, or BSON Long. The driver validates this because cluster times are gossiped between sharded/mongos nodes and an invalid signature would corrupt the $clusterTime sent on subsequent commands. It is a MongoInvalidArgumentError raised at the API boundary of advanceClusterTime.
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 3366c21a63)
Solutions
- Rehydrate the signature before calling advanceClusterTime: set signature.hash to new Binary(buffer, subtype) and signature.keyId to Long.fromString(String(keyId)) from the bson package.
- If the clusterTime came from another client's session.clusterTime getter, BSON-serialize then BSON-deserialize it instead of JSON round-tripping, so _bsontype markers survive.
- If you do not actually need to advance the cluster time manually, stop calling advanceClusterTime and let the driver manage it via command responses.
- Unit-test the clusterTime shape with a type guard (see defense) before passing it in.
Example fix
// before
const ct = JSON.parse(jsonClusterTime);
session.advanceClusterTime(ct); // throws: signature.hash/_bsontype missing
// after
import { Binary, Long } from 'bson';
const ct = JSON.parse(jsonClusterTime);
ct.signature = {
hash: new Binary(Buffer.from(ct.signature.hash.data), ct.signature.hash.subtype ?? 0),
keyId: Long.fromString(String(ct.signature.keyId))
};
session.advanceClusterTime(ct); Defensive patterns
Strategy: validation
Validate before calling
function isValidClusterTime(ct: any): boolean {
return (
ct != null && typeof ct === 'object' &&
ct.clusterTime?._bsontype === 'Timestamp' &&
ct.signature?.hash?._bsontype === 'Binary' &&
(typeof ct.signature?.keyId === 'bigint' ||
typeof ct.signature?.keyId === 'number' ||
ct.signature?.keyId?._bsontype === 'Long')
);
}
if (isValidClusterTime(ct)) session.advanceClusterTime(ct); Type guard
import type { ClusterTime } from 'mongodb';
function isClusterTime(v: unknown): v is ClusterTime {
return (
v != null && typeof v === 'object' &&
(v as any).clusterTime?._bsontype === 'Timestamp' &&
(v as any).signature?.hash?._bsontype === 'Binary'
);
} Try / catch
try {
session.advanceClusterTime(ct);
} catch (e) {
if (e instanceof MongoInvalidArgumentError) {
// rehydrate BSON types or skip advancing
} else throw e;
} Prevention
- BSON-serialize/deserialize cluster times instead of JSON round-tripping to preserve _bsontype.
- Prefer letting the driver manage clusterTime via command responses rather than advancing manually.
- Wrap any cluster-time gossip layer with the type guard above.
When it happens
Trigger: Calling session.advanceClusterTime(ct) where ct was built from JSON.parse (so _bsontype is gone), or hand-constructing a clusterTime object without rehydrating the hash into a BSON Binary and keyId into a BSON Long. Also reachable via session.clusterTime assignment paths that funnel through advanceClusterTime.
Common situations: Cross-client cluster-time gossip in sharded setups; deserializing a clusterTime received over a custom transport (HTTP/message queue) without BSON round-tripping; test fixtures that hardcode plain JS objects shaped like clusterTime.
Related errors
- input cluster time "clusterTime" property must be a valid BS
- Transaction already in progress
- ClientSession cannot be serialized to BSON.
- Function provided to `withTransaction` must return a Promise
- Document is larger than the maximum size ${this.s.maxBsonObj
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/b20c3488273c3d99.json.
Report an issue: GitHub.