denoland/deno · error · RangeError

Buffer size must be a multiple of 32-bits

Error message

Buffer size must be a multiple of 32-bits

What it means

Buffer.prototype.swap32() reverses bytes in place in 4-byte groups (32-bit endianness flip used for int32/float32 data). If the buffer's byte length is not a multiple of 4 it cannot be split into whole 32-bit words, so a plain RangeError is thrown before any byte is touched. Behavior matches Node exactly.

Source

Thrown at ext/node/polyfills/internal/buffer.mjs:682

  b[n] = b[m];
  b[m] = i;
}

Buffer.prototype.swap16 = function swap16() {
  const len = this.length;
  if (len % 2 !== 0) {
    throw new RangeError("Buffer size must be a multiple of 16-bits");
  }
  for (let i = 0; i < len; i += 2) {
    swap(this, i, i + 1);
  }
  return this;
};

Buffer.prototype.swap32 = function swap32() {
  const len = this.length;
  if (len % 4 !== 0) {
    throw new RangeError("Buffer size must be a multiple of 32-bits");
  }
  for (let i = 0; i < len; i += 4) {
    swap(this, i, i + 3);
    swap(this, i + 1, i + 2);
  }
  return this;
};

Buffer.prototype.swap64 = function swap64() {
  const len = this.length;
  if (len % 8 !== 0) {
    throw new RangeError("Buffer size must be a multiple of 64-bits");
  }
  for (let i = 0; i < len; i += 8) {
    swap(this, i, i + 7);
    swap(this, i + 1, i + 6);
    swap(this, i + 2, i + 5);
    swap(this, i + 3, i + 4);

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Verify length % 4 === 0 before swapping; treat a remainder as a truncated-read error
  2. Trim to a 4-byte boundary when trailing bytes are padding: buf.subarray(0, buf.length - buf.length % 4).swap32()
  3. Log the actual length at the read site - misalignment usually means the framing/length prefix was misparsed
  4. Pad to a multiple of 4 when the consumer format requires it

Example fix

// before
const buf = Buffer.from('abcde'); // 5 bytes
buf.swap32(); // RangeError: Buffer size must be a multiple of 32-bits

// after
const usable = buf.length - (buf.length % 4);
buf.subarray(0, usable).swap32();
Defensive patterns

Strategy: validation

Validate before calling

function swap32Safe(buf) {
  if (buf.length % 4 !== 0) {
    throw new RangeError(`expected byte length divisible by 4, got ${buf.length}`);
  }
  return buf.swap32();
}

Try / catch

try {
  buf.swap32();
} catch (e) {
  if (e instanceof RangeError) { /* trim to 4-byte boundary or refetch the record */ }
  else throw e;
}

Prevention

When it happens

Trigger: buf.swap32() when buf.length % 4 !== 0, e.g. Buffer.from([1,2,3,4,5]).swap32() (5 bytes) or a 10-byte record body read from a socket.

Common situations: Parsing fixed-width binary records (int32/float32 arrays, IP headers, WAV samples) where a partial read left the length misaligned; test buffers built from arbitrary strings; slicing errors that drop bytes from a record.

Related errors


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