{"record":{"id":"27b6b67539c0a9b4","repo":"denoland/deno","slug":"buffer-size-must-be-a-multiple-of-16-bits","errorCode":null,"errorMessage":"Buffer size must be a multiple of 16-bits","messagePattern":"Buffer size must be a multiple of 16-bits","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/buffer.mjs","lineNumber":671,"sourceCode":"  const ops = getEncodingOps(encoding);\n  if (ops === undefined) {\n    return (mustMatch ? -1 : byteLengthUtf8(string));\n  }\n  return ops.byteLength(string);\n}\n\nBuffer.byteLength = byteLength;\n\nfunction swap(b, n, m) {\n  const i = b[n];\n  b[n] = b[m];\n  b[m] = i;\n}\n\nBuffer.prototype.swap16 = function swap16() {\n  const len = this.length;\n  if (len % 2 !== 0) {\n    throw new RangeError(\"Buffer size must be a multiple of 16-bits\");\n  }\n  for (let i = 0; i < len; i += 2) {\n    swap(this, i, i + 1);\n  }\n  return this;\n};\n\nBuffer.prototype.swap32 = function swap32() {\n  const len = this.length;\n  if (len % 4 !== 0) {\n    throw new RangeError(\"Buffer size must be a multiple of 32-bits\");\n  }\n  for (let i = 0; i < len; i += 4) {\n    swap(this, i, i + 3);\n    swap(this, i + 1, i + 2);\n  }\n  return this;\n};","sourceCodeStart":653,"sourceCodeEnd":689,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/buffer.mjs#L653-L689","documentation":"Buffer.prototype.swap16() reverses bytes in place in 2-byte pairs (a 16-bit endianness flip, e.g. UTF-16LE <-> UTF-16BE). A buffer with an odd byte length cannot be divided into 2-byte pairs, so the method throws a plain RangeError before modifying any bytes. Same contract as Node's lib/internal/buffer.js.","triggerScenarios":"buf.swap16() when buf.length % 2 !== 0, e.g. Buffer.from('abc').swap16() (3 bytes) or a 101-byte network frame parsed as UTF-16.","commonSituations":"Decoding UTF-16 files with a truncated final code unit (broken download, wrong length from a header); odd-length test fixtures; an off-by-one in slicing that leaves one stray byte before conversion.","solutions":["Check alignment first and handle the trailing byte explicitly (report truncation or pad)","Trim to the largest even boundary when the last byte is padding: buf.subarray(0, buf.length - buf.length % 2).swap16()","Validate the source length (file size, Content-Length, protocol length field) before endian conversion - odd length usually means truncated input","Pad deliberately when the format expects it: Buffer.concat([buf, Buffer.alloc(1)]).swap16()"],"exampleFix":"// before\nconst buf = Buffer.from('abc'); // 3 bytes\nbuf.swap16(); // RangeError: Buffer size must be a multiple of 16-bits\n\n// after\nif (buf.length % 2 !== 0) throw new Error('truncated UTF-16 payload');\nbuf.swap16();","handlingStrategy":"validation","validationCode":"function swap16Safe(buf) {\n  if (buf.length % 2 !== 0) {\n    throw new RangeError(`expected even byte length, got ${buf.length}`);\n  }\n  return buf.swap16();\n}","typeGuard":null,"tryCatchPattern":"try {\n  buf.swap16();\n} catch (e) {\n  if (e instanceof RangeError) { /* record truncation, trim to even boundary, or refetch data */ }\n  else throw e;\n}","preventionTips":["Validate payload length against the protocol unit size before endian swaps","Centralize UTF-16 decode helpers that assert even length with a descriptive error","Test with odd-length inputs to surface truncation early"],"tags":["buffer","endianness","range-error","encoding","utf16"],"backgroundTag":"buffer-length-misaligned","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}