{"record":{"id":"b20c3488273c3d99","repo":"mongodb/node-mongodb-native","slug":"input-cluster-time-must-have-a-valid-signature-p","errorCode":null,"errorMessage":"input cluster time must have a valid \"signature\" property with BSON Binary hash and BSON Long keyId","messagePattern":"input cluster time must have a valid \"signature\" property with BSON Binary hash and BSON Long keyId","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/sessions.ts","lineNumber":336,"sourceCode":"   * @param clusterTime - the $clusterTime returned by the server from another session in the form of a document containing the `BSON.Timestamp` clusterTime and signature\n   */\n  advanceClusterTime(clusterTime: ClusterTime): void {\n    if (!clusterTime || typeof clusterTime !== 'object') {\n      throw new MongoInvalidArgumentError('input cluster time must be an object');\n    }\n    if (!clusterTime.clusterTime || clusterTime.clusterTime._bsontype !== 'Timestamp') {\n      throw new MongoInvalidArgumentError(\n        'input cluster time \"clusterTime\" property must be a valid BSON Timestamp'\n      );\n    }\n    if (\n      !clusterTime.signature ||\n      clusterTime.signature.hash?._bsontype !== 'Binary' ||\n      (typeof clusterTime.signature.keyId !== 'bigint' &&\n        typeof clusterTime.signature.keyId !== 'number' &&\n        clusterTime.signature.keyId?._bsontype !== 'Long') // apparently we decode the key to number?\n    ) {\n      throw new MongoInvalidArgumentError(\n        'input cluster time must have a valid \"signature\" property with BSON Binary hash and BSON Long keyId'\n      );\n    }\n\n    _advanceClusterTime(this, clusterTime);\n  }\n\n  /**\n   * Used to determine if this session equals another\n   *\n   * @param session - The session to compare to\n   */\n  equals(session: ClientSession): boolean {\n    if (!(session instanceof ClientSession)) {\n      return false;\n    }\n\n    if (this.id == null || session.id == null) {","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/sessions.ts#L318-L354","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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)`."],"exampleFix":"// before (after JSON round-trip — signature lost BSON types)\nsession.advanceClusterTime(jsonParsedClusterTime);\n\n// after\nimport { deserialize } from 'mongodb';\nconst ct = deserialize(serialisedBuffer);\nsession.advanceClusterTime(ct.$clusterTime);","handlingStrategy":"type-guard","validationCode":"function hasValidSignature(ct) {\n  const sig = ct?.signature;\n  return sig?.hash?._bsontype === 'Binary' &&\n    (typeof sig?.keyId === 'bigint' || typeof sig?.keyId === 'number' || sig?.keyId?._bsontype === 'Long');\n}\nif (hasValidSignature(ct)) session.advanceClusterTime(ct);","typeGuard":"function isValidSignedClusterTime(v) {\n  if (!v || typeof v !== 'object') return false;\n  if (v.clusterTime?._bsontype !== 'Timestamp') return false;\n  const sig = v.signature;\n  return sig?.hash?._bsontype === 'Binary' &&\n    (typeof sig?.keyId === 'bigint' || typeof sig?.keyId === 'number' || sig?.keyId?._bsontype === 'Long');\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["sessions","cluster-time","bson","validation","signature"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}