mongodb/node-mongodb-native · error · RangeError

Attempt to access memory outside buffer bounds: buffer lengt

Error message

Attempt to access memory outside buffer bounds: buffer length: ${buffer.length}, offset: ${offset}, length: ${length}

What it means

Thrown as a RangeError by the internal validateBufferInputs guard in src/bson.ts when a BSON read helper (readInt32LE / readUint8) is asked to read at an offset that is negative or where offset+length exceeds the buffer length. The driver uses this to fail fast on malformed or truncated BSON byte buffers during deserialization. It indicates the bytes presented to the parser do not contain a well-formed BSON document at the requested location.

Source

Thrown at src/bson.ts:45

  ObjectId,
  type ObjectIdLike,
  serialize,
  Timestamp,
  UUID
} from 'bson';

/** @internal */
export type BSONElement = BSON.OnDemand['BSONElement'];

export function parseToElementsToArray(bytes: Uint8Array, offset?: number): BSONElement[] {
  const res = BSON.onDemand.parseToElements(bytes, offset);
  return Array.isArray(res) ? res : [...res];
}

// validates buffer inputs, used for read operations
const validateBufferInputs = (buffer: Uint8Array, offset: number, length: number) => {
  if (offset < 0 || offset + length > buffer.length) {
    throw new RangeError(
      `Attempt to access memory outside buffer bounds: buffer length: ${buffer.length}, offset: ${offset}, length: ${length}`
    );
  }
};

// readInt32LE, reads a 32-bit integer from buffer at given offset
// throws if offset is out of bounds
export const readInt32LE = (buffer: Uint8Array, offset: number): number => {
  validateBufferInputs(buffer, offset, 4);
  return NumberUtils.getInt32LE(buffer, offset);
};

// readUint8, reads a single unsigned byte from buffer at given offset
export const readUint8 = (buffer: Uint8Array, offset: number): number => {
  validateBufferInputs(buffer, offset, 1);
  return buffer[offset];
};

View on GitHub (pinned to dce7939f86)

Solutions

  1. Verify the byte length of the Uint8Array you are deserializing before parsing; log buffer.length, offset, and the length prefix stored in the first 4 bytes to find the mismatch.
  2. Ensure the buffer was not truncated during transport (check socket/stream framing, message-length headers, and any manual subarray/slice math).
  3. If you compute offsets yourself, recompute them against the actual buffer.length and clamp before reading.
  4. If parsing concatenated BSON documents, validate each document's declared size fits inside the remaining bytes before advancing.

Example fix

// before: deserializing a possibly truncated buffer
const doc = deserialize(maybeTruncatedBytes);

// after: guard on length before parsing
function safeDeserialize(bytes: Uint8Array, offset = 0) {
  if (bytes.length - offset < 5) {
    throw new Error(`buffer too small for BSON doc: have ${bytes.length - offset} bytes`);
  }
  return deserialize(bytes.subarray(offset));
}
const doc = safeDeserialize(maybeTruncatedBytes);
Defensive patterns

Strategy: validation

Validate before calling

// Before deserializing, confirm the buffer can hold a BSON doc at the offset.
function assertReadable(bytes: Uint8Array, offset: number, length: number) {
  if (offset < 0 || offset + length > bytes.length) {
    throw new RangeError(
      `refusing to read: need [${offset}, ${offset + length}) of ${bytes.length}`
    );
  }
}

// usage
assertReadable(buf, 0, 4);
const sizeLe = buf.subarray(0, 4);
const docSize = NumberUtils.getInt32LE(sizeLe, 0);
assertReadable(buf, 0, docSize);

Type guard

// Narrow 'unknown bytes' to a non-empty, in-bounds view before parsing.
function isNonEmptyBytes(b: unknown): b is Uint8Array {
  return b instanceof Uint8Array && b.length > 0;
}

Try / catch

try {
  return deserialize(buf.subarray(offset));
} catch (e) {
  if (e instanceof RangeError && /outside buffer bounds/.test(e.message)) {
    throw new Error(`truncated BSON input: ${buf.length} bytes, offset ${offset}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: A Uint8Array that is too short (or an offset that points past its end) is passed to a BSON deserialization path. Concretely, calling a public API that decodes BSON (e.g. deserialize/parseToElements or an internal wire-protocol reply decoder) on a buffer that was truncated, double-sliced, or built from a mismatched length prefix. The condition is offset < 0 || offset + length > buffer.length inside validateBufferInputs at src/bson.ts:44.

Common situations: Hand-built or mutated wire payloads, buffers received over a stream that were cut off mid-message, a wrong length field in a custom protocol, reading from a SharedArrayBuffer/Buffer slice whose byteLength was miscomputed, or a corruption bug in code that manually advances an offset cursor while parsing BSON. Rarely seen in normal driver use; usually surfaces in tests, proxy tools, or when a user deserializes raw bytes from a non-driver source.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/b0b65ca87d1fedc6. Report an issue: GitHub.