{"id":"4f5a099821f04592","repo":"mongodb/node-mongodb-native","slug":"stream-end-options-end-must-not-be-negative","errorCode":null,"errorMessage":"Stream end (${options.end}) must not be negative","messagePattern":"Stream end \\((.+?)\\) must not be negative","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/gridfs/download.ts","lineNumber":471,"sourceCode":"    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":453,"sourceCodeEnd":484,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/gridfs/download.ts#L453-L484","documentation":"Despite the wording, handleEndOption throws this when end is set but start is null OR start is negative. The guard runs while validating the end option, so the error is surfaced in terms of end. Provide a non-negative start whenever you set end.","triggerScenarios":"bucket.openDownloadStream(id, { end: 100 }) with no start, or with start: -1.","commonSituations":"Setting an upper bound without a lower bound; negative start leaking into end validation; partial range config.","solutions":["Always pass a non-negative start when you set end (use start: 0 if you want the whole prefix)","Validate start >= 0 before opening the stream","Treat { start, end } as a required pair"],"exampleFix":"// before\nbucket.openDownloadStream(id, { end: 100 });\n// after\nbucket.openDownloadStream(id, { start: 0, end: 100 });","handlingStrategy":"validation","validationCode":"if (options.end != null) {\n  options.start = Math.max(0, options.start ?? 0);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pair end with a non-negative start (use 0 for whole prefix)","Treat { start, end } as a required pair"],"tags":["gridfs","stream","validation"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}