denoland/deno · error · ERR_OUT_OF_RANGE

ERR_OUT_OF_RANGE

ERR_OUT_OF_RANGE

Error message

The value of "offset" is out of range. It must be >= 0. Received ${offset}

What it means

validateOffsetLengthRead guards the destination window of fs.read(fd, buffer, offset, length, position): offset is where fetched bytes start landing inside buffer and cannot be negative. A negative offset is rejected before any I/O with ERR_OUT_OF_RANGE.

Source

Thrown at ext/node/polyfills/internal/fs/utils.mjs:858

    return +time;
  }
  if (NumberIsFinite(time)) {
    if (time < 0) {
      return DateNow() / 1000;
    }
    return time;
  }
  if (isDate(time)) {
    // Convert to 123.456 UNIX timestamp
    return DatePrototypeGetTime(time) / 1000;
  }
  throw new ERR_INVALID_ARG_TYPE(name, ["Date", "Time in seconds"], time);
}

export const validateOffsetLengthRead = hideStackFrames(
  (offset, length, bufferLength) => {
    if (offset < 0) {
      throw new ERR_OUT_OF_RANGE("offset", ">= 0", offset);
    }
    if (length < 0) {
      throw new ERR_OUT_OF_RANGE("length", ">= 0", length);
    }
    if (offset + length > bufferLength) {
      throw new ERR_OUT_OF_RANGE(
        "length",
        `<= ${bufferLength - offset}`,
        length,
      );
    }
  },
);

export const validateOffsetLengthWrite = hideStackFrames(
  (offset, length, byteLength) => {
    if (offset > byteLength) {
      throw new ERR_OUT_OF_RANGE("offset", `<= ${byteLength}`, offset);

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Ensure offset >= 0 — for whole-buffer reads it is simply 0.
  2. Re-check the signature: fs.read(fd, buffer, offset, length, position).
  3. Derive length from the view actually passed: buf.length - offset.

Example fix

// before
fs.readSync(fd, chunk, start - total, chunk.length, null); // start-total < 0 on short input

// after
const off = Math.max(0, start - total);
fs.readSync(fd, chunk, off, chunk.length - off, null);
Defensive patterns

Strategy: validation

Validate before calling

function checkReadWindow(offset, length, buf) {
  if (!(offset >= 0)) throw new RangeError(`offset must be >= 0, got ${offset}`);
  if (!(length >= 0)) throw new RangeError(`length must be >= 0, got ${length}`);
  if (offset + length > buf.length) throw new RangeError(`offset+length exceeds buffer of ${buf.length}`);
}

Prevention

When it happens

Trigger: fs.read(fd, buf, -1, 10, 0); offset computed as start - total going negative once the remaining bytes shrink; argument-order swaps where position lands in the offset slot.

Common situations: Hand-rolled chunked readers computing offsets from bytes-left arithmetic; code ported from C read(2) with different parameter meaning; off-by-one bugs after switching to Buffer.subarray views.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/a615bf707cec1df7. Report an issue: GitHub.