{"record":{"id":"b886a81c2fe1bb4e","repo":"mozilla/pdf.js","slug":"bad-begin-offset-begin","errorCode":null,"errorMessage":"Bad begin offset: ${begin}","messagePattern":"Bad begin offset: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/core/chunked_stream.js","lineNumber":64,"sourceCode":"      if (!this._loadedChunks.has(chunk)) {\n        chunks.push(chunk);\n      }\n    }\n    return chunks;\n  }\n\n  get numChunksLoaded() {\n    return this._loadedChunks.size;\n  }\n\n  get isDataLoaded() {\n    return this.numChunksLoaded === this.numChunks;\n  }\n\n  onReceiveData(begin, chunk) {\n    const chunkSize = this.chunkSize;\n    if (begin % chunkSize !== 0) {\n      throw new Error(`Bad begin offset: ${begin}`);\n    }\n\n    // Using `this.length` is inaccurate here since `this.start` can be moved\n    // (see the `moveStart` method).\n    const end = begin + chunk.byteLength;\n    if (end % chunkSize !== 0 && end !== this.bytes.length) {\n      throw new Error(`Bad end offset: ${end}`);\n    }\n\n    if (typeof PDFJSDev === \"undefined\" || PDFJSDev.test(\"TESTING\")) {\n      assert(\n        chunk instanceof ArrayBuffer,\n        \"onReceiveData - expected an ArrayBuffer.\"\n      );\n    }\n    this.bytes.set(new Uint8Array(chunk), begin);\n    const beginChunk = Math.floor(begin / chunkSize);\n    const endChunk = Math.floor((end - 1) / chunkSize) + 1;","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/chunked_stream.js#L46-L82","documentation":"Thrown by ChunkedStream.onReceiveData when the incoming data's `begin` offset is not an exact multiple of the stream's chunkSize. ChunkedStream partitions a PDF into fixed-size chunks and requires all received ranges to be chunk-aligned so it can mark the correct _loadedChunks entries.","triggerScenarios":"A range-request server or custom PDFDataTransportStream returns data at a byte offset that is not a multiple of chunkSize (e.g., chunkSize 65536 but data arrives at offset 1000). onReceiveData is called by the transport when chunked/range streaming is enabled.","commonSituations":"A CDN or reverse proxy that re-chunks responses or strips Content-Range alignment; a custom Range header implementation computing offsets incorrectly; mismatched chunkSize between server and client; HTTP/2 framing that splits the body at non-chunk boundaries; a misconfigured PDFJS.disableRange or rangeChunkSize option.","solutions":["Ensure the server honors Range requests and returns bodies aligned to the client's rangeChunkSize (default 65536).","Verify rangeChunkSize passed to getDocument matches what your transport actually delivers.","If you cannot control alignment, disable range/streamed loading (set disableRange: true, disableStream: true) so the full file is fetched.","Inspect the transport layer (PDFDataRangeTransport or fetch_stream) for incorrect begin values being passed to onReceiveData."],"exampleFix":"// before\nconst loadingTask = pdfjsLib.getDocument({ url, rangeChunkSize: 65536 });\n// server returns misaligned ranges -> throw\n\n// after (option A: disable range loading)\nconst loadingTask = pdfjsLib.getDocument({\n  url,\n  disableRange: true,\n  disableStream: true,\n});\n\n// after (option B: align server Range responses to rangeChunkSize)\n// ensure the origin returns Content-Range whose start is a multiple of 65536","handlingStrategy":"validation","validationCode":"// Validate chunk alignment before forwarding to onReceiveData.\nfunction validateChunkAlignment(stream, begin, chunk) {\n  if (begin % stream.chunkSize !== 0) {\n    throw new Error(`Misaligned chunk: begin=${begin} chunkSize=${stream.chunkSize}`);\n  }\n  const end = begin + chunk.byteLength;\n  if (end % stream.chunkSize !== 0 && end !== stream.bytes.length) {\n    throw new Error(`Misaligned chunk end: end=${end}`);\n  }\n}","typeGuard":"function isChunkAligned(begin, chunkSize) {\n  return Number.isInteger(begin) && begin >= 0 && begin % chunkSize === 0;\n}","tryCatchPattern":"try {\n  stream.onReceiveData(begin, chunk);\n} catch (e) {\n  // Transport delivered misaligned data; fall back to full-file fetch.\n  console.warn('Chunked stream alignment error; disabling range loading:', e);\n  // Re-load with disableRange: true\n}","preventionTips":["Ensure your server honors Range requests and returns chunk-aligned bodies.","Keep rangeChunkSize consistent with the byte boundaries your transport delivers.","If alignment cannot be guaranteed, load with disableRange: true and disableStream: true.","Inspect PDFDataRangeTransport/fetch_stream begin values when wiring a custom transport."],"tags":["pdf","chunked-stream","range-request","transport","network","streaming"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}