{"record":{"id":"7aa9d2c08f16c8ce","repo":"mongodb/node-mongodb-native","slug":"stream-start-options-start-must-not-be-more-t","errorCode":null,"errorMessage":"Stream start (${options.start}) must not be more than the length of the file (${doc.length})","messagePattern":"Stream start \\((.+?)\\) must not be more than the length of the file \\((.+?)\\)","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/gridfs/download.ts","lineNumber":437,"sourceCode":"\n  if (!stream.s.init) {\n    init(stream);\n    stream.s.init = true;\n  }\n\n  stream.once('file', () => {\n    callback();\n  });\n}\n\nfunction handleStartOption(\n  stream: GridFSBucketReadStream,\n  doc: Document,\n  options: GridFSBucketReadStreamOptions\n): number {\n  if (options && options.start != null) {\n    if (options.start > doc.length) {\n      throw new MongoInvalidArgumentError(\n        `Stream start (${options.start}) must not be more than the length of the file (${doc.length})`\n      );\n    }\n    if (options.start < 0) {\n      throw new MongoInvalidArgumentError(`Stream start (${options.start}) must not be negative`);\n    }\n    if (options.end != null && options.end < options.start) {\n      throw new MongoInvalidArgumentError(\n        `Stream start (${options.start}) must not be greater than stream end (${options.end})`\n      );\n    }\n\n    stream.s.bytesRead = Math.floor(options.start / doc.chunkSize) * doc.chunkSize;\n    stream.s.expected = Math.floor(options.start / doc.chunkSize);\n\n    return options.start - stream.s.bytesRead;\n  }\n  throw new MongoInvalidArgumentError('Start option must be defined');","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/gridfs/download.ts#L419-L455","documentation":"When opening a GridFS download stream with a start offset, handleStartOption (src/gridfs/download.ts:435) validates the value against the file's actual length. If start exceeds doc.length, it throws MongoInvalidArgumentError. This fires during stream initialization once the file document has been fetched.","triggerScenarios":"Calling openDownloadStream(id, { start: N }) where N is greater than the stored file's length. Using a hardcoded offset that is valid for larger files but not for a shorter one being read.","commonSituations":"Assuming a file is larger than it is (e.g. resuming a download with a stale byte offset after the file was replaced). Computing start from an unverified external source without checking file size.","solutions":["Fetch the file metadata first (bucket.find({ _id: id })) and confirm start <= file.length before opening the stream.","Clamp start to the file length, or to 0, if a partial read beyond the end should be treated as empty.","Validate user-provided range inputs against the known file size before passing them to openDownloadStream."],"exampleFix":"// before\nconst s = bucket.openDownloadStream(id, { start: 100000 });\n// after\nconst file = await bucket.find({ _id: id }).next();\nconst s = bucket.openDownloadStream(id, { start: Math.min(100000, file.length) });","handlingStrategy":"validation","validationCode":"async function safeOpen(bucket, id, range) {\n  const file = await bucket.find({ _id: id }).next();\n  if (!file) throw new Error('file not found');\n  if (range?.start != null && range.start > file.length) {\n    range.start = file.length;\n  }\n  return bucket.openDownloadStream(id, range);\n}","typeGuard":"function isStartWithinLength(start: number, length: number): boolean {\n  return Number.isInteger(start) && start >= 0 && start <= length;\n}","tryCatchPattern":"try {\n  return bucket.openDownloadStream(id, { start });\n} catch (e) {\n  if (e instanceof MongoInvalidArgumentError && /must not be more than the length/.test(e.message)) {\n    // fetch length and clamp start\n  }\n  throw e;\n}","preventionTips":["Always fetch file metadata before computing range offsets.","Clamp start to file length before opening the stream.","Validate user-provided byte ranges against the known file size."],"tags":["gridfs","stream","validation","range"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}