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

  1. 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.
  2. 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.
  3. If you do not actually need to advance the cluster time manually, stop calling advanceClusterTime and let the driver manage it via command responses.
  4. 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

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


AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04). Data as JSON: /data/errors/b20c3488273c3d99.json. Report an issue: GitHub.