{"record":{"id":"93e2479a5c42bf62","repo":"mongodb/node-mongodb-native","slug":"stream-end-options-end-must-not-be-more-than","errorCode":null,"errorMessage":"Stream end (${options.end}) must not be more than the length of the file (${doc.length})","messagePattern":"Stream end \\((.+?)\\) must not be more than the length of the file \\((.+?)\\)","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/gridfs/download.ts","lineNumber":466,"sourceCode":"    }\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');\n}\n\nfunction handleEndOption(\n  stream: GridFSBucketReadStream,\n  doc: Document,\n  cursor: FindCursor<GridFSChunk>,\n  options: GridFSBucketReadStreamOptions\n) {\n  if (options && options.end != null) {\n    if (options.end > doc.length) {\n      throw new MongoInvalidArgumentError(\n        `Stream end (${options.end}) must not be more than the length of the file (${doc.length})`\n      );\n    }\n    if (options.start == null || options.start < 0) {\n      throw new MongoInvalidArgumentError(`Stream end (${options.end}) must not be negative`);\n    }\n\n    const start = options.start != null ? Math.floor(options.start / doc.chunkSize) : 0;\n\n    cursor.limit(Math.ceil(options.end / doc.chunkSize) - start);\n\n    stream.s.expectedEnd = Math.ceil(options.end / doc.chunkSize);\n\n    return Math.ceil(options.end / doc.chunkSize) * doc.chunkSize - options.end;\n  }\n  throw new MongoInvalidArgumentError('End option must be defined');\n}\n","sourceCodeStart":448,"sourceCodeEnd":484,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/gridfs/download.ts#L448-L484","documentation":"handleEndOption (src/gridfs/download.ts:465) validates that the end offset does not exceed the file's actual length (doc.length). If end is greater than the stored size, it throws MongoInvalidArgumentError during stream initialization.","triggerScenarios":"Calling openDownloadStream(id, { end: N }) where N > file length. Passing a hardcoded end offset that is valid for some files but not for a shorter one.","commonSituations":"Assuming a file is larger than it is (e.g. reading with end from a stale content-length header). Using the same range for files of differing sizes.","solutions":["Fetch the file metadata (bucket.find({ _id: id })) and confirm end <= file.length before opening the stream.","Clamp end to the file length: Math.min(end, file.length)."],"exampleFix":"// before\nconst s = bucket.openDownloadStream(id, { end: 500000 });\n// after\nconst file = await bucket.find({ _id: id }).next();\nconst s = bucket.openDownloadStream(id, { end: Math.min(500000, file.length) });","handlingStrategy":"validation","validationCode":"async function safeOpenEnd(bucket, id, end) {\n  const file = await bucket.find({ _id: id }).next();\n  if (!file) throw new Error('file not found');\n  if (end > file.length) end = file.length;\n  return bucket.openDownloadStream(id, { start: 0, end });\n}","typeGuard":"function isEndWithinLength(end: number, length: number): boolean {\n  return Number.isInteger(end) && end >= 0 && end <= length;\n}","tryCatchPattern":"try {\n  bucket.openDownloadStream(id, { start: 0, end });\n} catch (e) {\n  if (e instanceof MongoInvalidArgumentError && /must not be more than the length/.test(e.message)) {\n    // clamp end to length\n  }\n}","preventionTips":["Fetch file metadata before computing end offsets.","Clamp end to file.length.","Validate range inputs against the real 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"}