denoland/deno · error · NodeRangeError
ERR_OUT_OF_RANGE
ERR_OUT_OF_RANGE
Error message
The value of "start" is out of range. It must be <= "end" (here: ${this.end}). Received ${actual} What it means
In the ReadStream constructor, start is validated as an integer >= 0 and, whenever end is not Infinity, start must not exceed end. A byte window whose first byte lies past its last byte cannot be read, so construction fails with ERR_OUT_OF_RANGE reporting the actual end value.
Source
Thrown at ext/node/polyfills/internal/fs/streams.mjs:254
}
this.start = options.start;
this.end = options.end ?? NumberPOSITIVE_INFINITY;
this.pos = undefined;
this.bytesRead = 0;
this[kIsPerformingIO] = false;
if (this.start !== undefined) {
validateInteger(this.start, "start", 0);
this.pos = this.start;
}
if (this.end !== NumberPOSITIVE_INFINITY) {
validateInteger(this.end, "end", 0);
if (this.start !== undefined && this.start > this.end) {
throw new ERR_OUT_OF_RANGE(
"start",
`<= "end" (here: ${this.end})`,
this.start,
);
}
}
ReflectApply(lazyStream().Readable, this, [options]);
}
ObjectSetPrototypeOf(ReadStream.prototype, lazyStream().Readable.prototype);
ObjectSetPrototypeOf(ReadStream, lazyStream().Readable);
ObjectDefineProperty(ReadStream.prototype, "autoClose", {
__proto__: null,
get() {
return this._readableState.autoDestroy;
},View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Fix the range so start <= end — usually the two bounds are swapped.
- Omit end when reading to EOF; it defaults to Infinity and the comparison is skipped.
- Clamp defensively before constructing: start = Math.min(start, end).
Example fix
// before
const s = fs.createReadStream(f, { start: 100, end: 50 }); // throws
// after
const s = fs.createReadStream(f, { start: 50, end: 100 });
// or read to EOF from an offset
const s = fs.createReadStream(f, { start: 50 }); Defensive patterns
Strategy: validation
Validate before calling
function validRange(o = {}) {
const end = o.end ?? Infinity;
if (o.start === undefined) return true;
return Number.isInteger(o.start) && o.start >= 0 && o.start <= end;
}
if (!validRange(opts)) throw new RangeError('start must be an integer >= 0 and <= end'); Prevention
- Compute ranges from a single source of truth such as stat().size.
- Sort unknown-order bounds before use: [a, b].sort((x, y) => x - y).
- Log start/end right before createReadStream in range-serving code.
When it happens
Trigger: fs.createReadStream(f, { start: 100, end: 50 }); range math that swaps the bounds or derives end from a shorter content-length; { start: -1 } also fails earlier via validateInteger.
Common situations: HTTP Range-request handlers translating headers into stream options; download resume logic where start equals the new file size but end was computed from the old size; reversed pagination indexes from a UI feeding a file slicer.
Related errors
- Selector must specify either 'prefix' or both 'start' and 'e
- ERR_OUT_OF_RANGE
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_ARG_VALUE
- ERR_FS_INVALID_SYMLINK_TYPE
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/3ba984b83cc9f7db.
Report an issue: GitHub.