{"id":"b5ba08685a791729","repo":"mongodb/node-mongodb-native","slug":"unable-to-iterate-cursor-with-no-id","errorCode":null,"errorMessage":"Unable to iterate cursor with no id","messagePattern":"Unable to iterate cursor with no id","errorType":"exception","errorClass":"MongoRuntimeError","httpStatus":null,"severity":"error","filePath":"src/operations/get_more.ts","lineNumber":58,"sourceCode":"  cursorId: Long;\n  override options: GetMoreOptions;\n\n  constructor(ns: MongoDBNamespace, cursorId: Long, server: Server, options: GetMoreOptions) {\n    super(options);\n\n    this.options = options;\n    this.ns = ns;\n    this.cursorId = cursorId;\n    this.server = server;\n  }\n\n  override get commandName() {\n    return 'getMore' as const;\n  }\n\n  override buildCommand(_connection: Connection): Document {\n    if (this.cursorId == null || this.cursorId.isZero()) {\n      throw new MongoRuntimeError('Unable to iterate cursor with no id');\n    }\n\n    const collection = this.ns.collection;\n    if (collection == null) {\n      // Cursors should have adopted the namespace returned by MongoDB\n      // which should always defined a collection name (even a pseudo one, ex. db.aggregate())\n      throw new MongoRuntimeError('A collection name must be determined before getMore');\n    }\n\n    const getMoreCmd: GetMoreCommand = {\n      getMore: this.cursorId,\n      collection\n    };\n\n    if (typeof this.options.batchSize === 'number') {\n      getMoreCmd.batchSize = Math.abs(this.options.batchSize);\n    }\n","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/operations/get_more.ts#L40-L76","documentation":"Thrown by GetMoreOperation.buildCommand when the cursor being iterated has a null or zero cursor id. A zero id means no server-side cursor exists - either the initial batch already exhausted the result set, the cursor was already closed, or it was never successfully created. This is a MongoRuntimeError indicating invalid driver/cursor state rather than a bad user argument.","triggerScenarios":"Iterating a cursor a second time after it was fully consumed or explicitly closed; iterating a cursor whose initial command returned id 0 (small result set returned in the first batch); a race where killCursors ran between batches; calling .next()/.toArray() on a cursor after an error already tore it down; manually reusing a cursor object across async boundaries.","commonSituations":"Storing a cursor in a shared variable and iterating it from two places; awaiting toArray() then calling toArray() again; tailable/change-stream cursors during shutdown; retry logic that re-enters a cursor loop after a transient failure without re-creating the cursor.","solutions":["Do not reuse a cursor after exhaustion - re-issue the query/find/aggregate to obtain a fresh cursor.","Ensure you fully consume a cursor exactly once (single toArray()/for-await loop).","If iterating in pages, capture the cursor once and drive it linearly; don't hand the same cursor to concurrent consumers.","On transient errors, restart the whole operation (new find/aggregate) rather than resuming the dead cursor."],"exampleFix":"// before - reusing an exhausted cursor\ncursor = collection.find({});\nawait cursor.toArray();\nawait cursor.next(); // throws: no id\n// after - create a new cursor for each iteration\nawait collection.find({}).toArray();","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await cursor.next();\n} catch (e) {\n  if (e instanceof MongoRuntimeError && /no id/.test(e.message)) {\n    // cursor is exhausted/dead - re-run the query to get a fresh cursor instead of resuming\n    cursor = collection.find(filter);\n  } else throw e;\n}","preventionTips":["Never iterate the same cursor twice or from two concurrent consumers.","Re-issue the query to obtain a fresh cursor after exhaustion or error.","Consume cursors via a single for-await loop or a single toArray() call."],"tags":["cursor","getmore","runtime-error","lifecycle"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}