{"record":{"id":"f59c889a50c49a00","repo":"mozilla/pdf.js","slug":"bad-end-offset-end","errorCode":null,"errorMessage":"Bad end offset: ${end}","messagePattern":"Bad end offset: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/core/chunked_stream.js","lineNumber":71,"sourceCode":"  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;\n\n    for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {\n      // Since a value can only occur *once* in a `Set`, there's no need to\n      // manually check `Set.prototype.has()` before adding the value here.\n      this._loadedChunks.add(curChunk);\n    }\n  }","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/chunked_stream.js#L53-L89","documentation":"Thrown by ChunkedStream.onReceiveData when a delivered chunk's end position (begin + chunk.byteLength) is neither aligned to chunkSize nor exactly equal to the document's total byte length. The library enforces this so its internal _loadedChunks set stays consistent with the chunk grid. A violation means the byte-range transport and the configured chunkSize disagree about chunk boundaries.","triggerScenarios":"Calling onReceiveData(begin, chunk) where (begin + chunk.byteLength) % chunkSize !== 0 and the end is not the final byte. Occurs when a Range-request server returns responses whose sizes differ from the client's rangeChunkSize, when Content-Range/Content-Length disagree, or when a custom network/stream-reader layer passes mis-sized chunks.","commonSituations":"Self-hosted PDF behind a CDN or reverse proxy that re-chunks responses; mismatched rangeChunkSize between client and origin server; multi-part/byteranges responses served in arbitrary pieces; a server that ignores Range headers and streams the whole file split arbitrarily.","solutions":["Align server Range responses to the rangeChunkSize value passed to getDocument so every served chunk starts and ends on a chunkSize boundary.","Verify Content-Range and Content-Length headers agree with the byte range the client requested.","If you implement a custom IPDFFileStreamReader/NetworkLayer, return chunks whose begin and end are multiples of chunkSize (the final chunk excepted).","Disable range requests via getDocument({ disableRange: true }) when the server cannot honor aligned ranges."],"exampleFix":"// before\nstream.onReceiveData(begin, chunk); // begin=5000, chunkSize=65536\n\n// after\nconst cs = stream.chunkSize;\nconst end = begin + chunk.byteLength;\nif (begin % cs === 0 && (end % cs === 0 || end === stream.bytes.length)) {\n  stream.onReceiveData(begin, chunk);\n} else {\n  console.warn('Ignoring mis-aligned chunk', { begin, end, cs });\n}","handlingStrategy":"validation","validationCode":"// Validate chunk alignment before invoking onReceiveData\nfunction safeReceiveData(stream, begin, chunk) {\n  const cs = stream.chunkSize;\n  const end = begin + chunk.byteLength;\n  if (begin % cs !== 0) {\n    console.warn('begin not aligned', { begin, cs });\n    return false;\n  }\n  if (end % cs !== 0 && end !== stream.bytes.length) {\n    console.warn('end not aligned', { end, cs, total: stream.bytes.length });\n    return false;\n  }\n  stream.onReceiveData(begin, chunk);\n  return true;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set rangeChunkSize to a value the server can honor exactly for every served range.","Use disableRange: true for servers that ignore or mangle Range headers.","Inspect Content-Range/Content-Length headers in DevTools before wiring up a custom transport.","If implementing a custom stream reader, return chunks aligned to chunkSize boundaries."],"tags":["streaming","network","chunked","range-requests","pdf"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}