{"record":{"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/dce7939f86fb283e167ad709955abedb7bf23124/src/operations/get_more.ts#L40-L76","documentation":"Thrown as a MongoRuntimeError by GetMoreOperation.buildCommand when the cursorId is null or zero (this.cursorId.isZero()). A zero cursor id means the server has already closed the cursor (it returned id 0 indicating no more batches), so issuing getMore is invalid. This usually surfaces as an attempt to iterate an already-exhausted or closed cursor.","triggerScenarios":"Continuing to call cursor.next() / for-await after the cursor has been fully drained (server returned cursorId 0), or calling .next() on a cursor that was explicitly closed. The check is at get_more.ts:57.","commonSituations":"Looping over a cursor without checking for done; reusing a cursor after iteration completed; concurrency where one consumer closes the cursor while another iterates; transforming a cursor to an array then iterating again.","solutions":["Stop iterating once the cursor is exhausted (for-await-of ends naturally; check (await cursor.next()) === null).","Do not reuse a cursor after it has been closed or fully iterated; create a new query instead.","Avoid concurrent iteration of the same cursor."],"exampleFix":"// before\nconst cursor = coll.find({});\nawait cursor.forEach(()=>{});\nawait cursor.next(); // cursor exhausted -> error\n\n// after\nconst cursor = coll.find({});\nawait cursor.forEach(()=>{});\n// start a fresh query if you need the data again\nconst fresh = coll.find({});","handlingStrategy":"validation","validationCode":"import type { FindCursor } from 'mongodb';\n\nasync function safelyNext<T>(cursor: FindCursor<T>): Promise<T | null> {\n  // Respect cursor exhaustion; do not call next after the cursor reports closed\n  if (cursor.closed) return null;\n  return cursor.next();\n}","typeGuard":null,"tryCatchPattern":"try {\n  await cursor.next();\n} catch (err) {\n  if (err instanceof MongoRuntimeError && /no id/.test(err.message)) {\n    // cursor already exhausted; stop iterating\n  } else throw err;\n}","preventionTips":["Use for-await-of to iterate; it stops naturally when the cursor is drained.","Do not call .next() after forEach/toArray completes; start a new query instead.","Never iterate the same cursor concurrently."],"tags":["cursor","getmore","runtime","iteration"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}