{"record":{"id":"2a47a549773d38f3","repo":"denoland/deno","slug":"err-buffer-out-of-bounds","errorCode":"ERR_BUFFER_OUT_OF_BOUNDS","errorMessage":"\"offset\" is outside of buffer bounds","messagePattern":"\"offset\" is outside of buffer bounds","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/dgram.ts","lineNumber":1473,"sourceCode":"}\n\nfunction sliceBuffer(buffer: MessageType, offset: number, length: number) {\n  if (typeof buffer === \"string\") {\n    buffer = Buffer.from(buffer);\n  } else if (!isArrayBufferView(buffer)) {\n    throw new ERR_INVALID_ARG_TYPE(\n      \"buffer\",\n      [\"Buffer\", \"TypedArray\", \"DataView\", \"string\"],\n      buffer,\n    );\n  }\n\n  offset = offset >>> 0;\n  length = length >>> 0;\n\n  // deno-lint-ignore deno-internal/prefer-primordials -- buffer may be a Buffer or DataView, not a plain TypedArray\n  if (offset > buffer.byteLength) {\n    throw new ERR_BUFFER_OUT_OF_BOUNDS(\"offset\");\n  }\n\n  // deno-lint-ignore deno-internal/prefer-primordials -- buffer may be a Buffer or DataView, not a plain TypedArray\n  if (offset + length > buffer.byteLength) {\n    throw new ERR_BUFFER_OUT_OF_BOUNDS(\"length\");\n  }\n\n  // deno-lint-ignore deno-internal/prefer-primordials -- Buffer is the Node Buffer class; .buffer/.byteOffset on a Buffer or DataView\n  return Buffer.from(buffer.buffer, buffer.byteOffset + offset, length);\n}\n\nfunction fixBufferList(\n  list: ReadonlyArray<MessageType>,\n): Array<MessageType> | null {\n  const newList = new Array(list.length);\n\n  for (let i = 0, l = list.length; i < l; i++) {\n    const buf = list[i];","sourceCodeStart":1455,"sourceCodeEnd":1491,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/node/polyfills/dgram.ts#L1455-L1491","documentation":"In sliceBuffer(), after offset is coerced with 'offset >>> 0' it must not exceed buffer.byteLength, otherwise ERR_BUFFER_OUT_OF_BOUNDS('offset') is thrown. The >>> 0 coercion means a negative offset becomes a huge uint32 and virtually always fails this check.","triggerScenarios":"sock.send(buf, 2048, 10, port, host) with a 1024-byte buffer; sock.send(buf, -8, 16, port) (becomes 0xFFFFFFF8 after >>> 0); offsets computed from a header size larger than the payload.","commonSituations":"Offsets from protocol headers (e.g. skipping a 12-byte DNS header on short packets); arithmetic that goes negative on truncated data; using bit offsets instead of byte offsets.","solutions":["Clamp before calling: offset = Math.max(0, Math.min(offset, buf.byteLength))","Validate the packet actually contains the header: if (buf.length < HEADER_LEN) drop/ignore it","Remember offset is in bytes and is uint32-coerced — negatives are never valid"],"exampleFix":"// before\nsock.send(pkt, 12, pkt.length - 12, port, host); // throws when pkt.length < 12\n\n// after\nif (pkt.length < 12) return; // or handle short packet\nsock.send(pkt, 12, pkt.length - 12, port, host);","handlingStrategy":"validation","validationCode":"const off = offset >>> 0;\nif (!(off <= buffer.byteLength)) {\n  throw new RangeError(`offset ${offset} out of bounds for ${buffer.byteLength} bytes`);\n}\nsock.send(buffer, off, length, port, host, cb);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check payload length covers the protocol header before slicing","Clamp offsets: Math.max(0, Math.min(offset, buf.byteLength))","Never pass negative offsets — >>> 0 turns them into huge uint32s"],"tags":["node-compat","dgram","buffer","bounds-check"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}