{"record":{"id":"036db0986b0017c7","repo":"parallax/jsPDF","slug":"frame-index-out-of-range","errorCode":null,"errorMessage":"Frame index out of range.","messagePattern":"Frame index out of range\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/libs/omggif.js","lineNumber":606,"sourceCode":"        break;\n\n      default:\n        throw new Error(\"Unknown gif block: 0x\" + buf[p - 1].toString(16));\n        break;\n    }\n  }\n\n  this.numFrames = function() {\n    return frames.length;\n  };\n\n  this.loopCount = function() {\n    return loop_count;\n  };\n\n  this.frameInfo = function(frame_num) {\n    if (frame_num < 0 || frame_num >= frames.length)\n      throw new Error(\"Frame index out of range.\");\n    return frames[frame_num];\n  };\n\n  this.decodeAndBlitFrameBGRA = function(frame_num, pixels) {\n    var frame = this.frameInfo(frame_num);\n    var num_pixels = frame.width * frame.height;\n\n    if (num_pixels > 512 * 1024 * 1024) {\n      throw new Error(\"Image dimensions exceed 512MB, which is too large.\");\n    }\n\n    var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.\n    GifReaderLZWOutputIndexStream(\n      buf,\n      frame.data_offset,\n      index_stream,\n      num_pixels\n    );","sourceCodeStart":588,"sourceCodeEnd":624,"githubUrl":"https://github.com/parallax/jsPDF/blob/a3930ce03a585a26b2c76d12a0f413ce96f6d1a3/src/libs/omggif.js#L588-L624","documentation":"Thrown by GifReader.frameInfo(frame_num) when the requested frame index is negative or >= frames.length. frameInfo is the entry point used by both decodeAndBlitFrameBGRA and decodeAndBlitFrameRGBA, so any out-of-range frame decode hits this. It is a standard bounds guard for an animated GIF's frame table.","triggerScenarios":"Calling reader.decodeAndBlitFrameRGBA(n, pixels) / reader.frameInfo(n) where n is beyond the last frame, negative, or a non-integer. Commonly n equals the frame count (off-by-one) or is hardcoded to a frame index that a single-frame GIF does not have.","commonSituations":"Decoding an animated GIF and looping `i <= reader.numFrames()` instead of `<`; passing a user-supplied frame number without clamping; jsPDF's processGIF89A hardcodes frame 0 so this only bites custom GifReader usage.","solutions":["Bounds-check against reader.numFrames() before decoding: require 0 <= frame_num < reader.numFrames().","Use strict less-than in loops over frames.","If the caller exposes a frame picker, clamp or reject out-of-range input before calling the decoder."],"exampleFix":"// before\nfor (var i = 0; i <= reader.numFrames(); i++) {\n  reader.decodeAndBlitFrameRGBA(i, pixels);\n}\n\n// after\nfor (var i = 0; i < reader.numFrames(); i++) {\n  reader.decodeAndBlitFrameRGBA(i, pixels);\n}","handlingStrategy":"validation","validationCode":"var n = reader.numFrames();\nif (!(frameNum >= 0 && frameNum < n)) {\n  throw new Error('frameNum ' + frameNum + ' out of range [0,' + n + ')');\n}\nreader.decodeAndBlitFrameRGBA(frameNum, pixels);","typeGuard":"function isValidFrameIndex(reader, i) {\n  return Number.isInteger(i) && i >= 0 && i < reader.numFrames();\n}","tryCatchPattern":"try {\n  reader.frameInfo(frameNum);\n} catch (e) {\n  if (/Frame index out of range/.test(e.message)) {\n    return null; // clamp or skip\n  }\n  throw e;\n}","preventionTips":["Always loop frames with `i < reader.numFrames()` (strict less-than).","Clamp user-supplied frame numbers into [0, numFrames-1].","Default to frame 0 when the requested frame is unavailable."],"tags":["gif","bounds-check","omggif"],"backgroundTag":null,"analyzedSha":"a3930ce03a585a26b2c76d12a0f413ce96f6d1a3","analyzedAt":"2026-08-13T05:33:39.648Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}