{"record":{"id":"677c18ce0c06c335","repo":"koral--/android-gif-drawable","slug":"frame-index-is-not-in-range-0-numberofframes","errorCode":null,"errorMessage":"Frame index is not in range <0;<numberOfFrames>>","messagePattern":"Frame index is not in range <0;<numberOfFrames>>","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifInfoHandle.java","lineNumber":372,"sourceCode":"\t}\n\n\tvoid stopDecoderThread() {\n\t\tstopDecoderThread(gifInfoPtr);\n\t}\n\n\tvoid initTexImageDescriptor() {\n\t\tinitTexImageDescriptor(gifInfoPtr);\n\t}\n\n\tvoid seekToFrameGL(@IntRange(from = 0) final int index) {\n\t\tthrowIfFrameIndexOutOfBounds(index);\n\t\tseekToFrameGL(gifInfoPtr, index);\n\t}\n\n\tprivate void throwIfFrameIndexOutOfBounds(@IntRange(from = 0) final int index) {\n\t\tfinal int numberOfFrames = getNumberOfFrames(gifInfoPtr);\n\t\tif (index < 0 || index >= numberOfFrames) {\n\t\t\tthrow new IndexOutOfBoundsException(\"Frame index is not in range <0;\" + numberOfFrames + '>');\n\t\t}\n\t}\n}","sourceCodeStart":354,"sourceCodeEnd":375,"githubUrl":"https://github.com/koral--/android-gif-drawable/blob/26ff795f78b7fe8bbaf375a947b2bda95fc58e3d/android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifInfoHandle.java#L354-L375","documentation":"throwIfFrameIndexOutOfBounds verifies a frame index against the GIF's total frame count and throws IndexOutOfBoundsException('Frame index is not in range <0;<numberOfFrames>>') when index < 0 or index >= numberOfFrames. It guards frame-addressing calls like getFrameDuration and seekToFrameGL.","triggerScenarios":"Calling getFrameDuration(index) or seekToFrame index >= getNumberOfFrames(), or a negative index; often caching a frame index across different GIFs with fewer frames.","commonSituations":"Iterating frames with an off-by-one (<= numberOfFrames); hardcoding frame numbers; reusing indices after loading a shorter GIF.","solutions":["Check index against gifDrawable.getNumberOfFrames() (or getNumberOfFrame on handle) before use.","Fix off-by-one loops: iterate i < numberOfFrames, not <=.","Clamp or wrap the index: Math.min(index, numberOfFrames - 1)."],"exampleFix":"// before\nint duration = gifInfoHandle.getFrameDuration(frameIndex);\n// after\nif (frameIndex >= 0 && frameIndex < gifInfoHandle.getNumberOfFrames()) {\n    int duration = gifInfoHandle.getFrameDuration(frameIndex);\n}","handlingStrategy":"validation","validationCode":"if (index >= 0 && index < gifInfoHandle.getNumberOfFrames()) { gifInfoHandle.getFrameDuration(index); }","typeGuard":"boolean isFrameIndexValid(GifInfoHandle h, int i) { return i >= 0 && i < h.getNumberOfFrames(); }","tryCatchPattern":"try { int d = gifInfoHandle.getFrameDuration(index); } catch (IndexOutOfBoundsException e) { /* clamp index or skip */ }","preventionTips":["Iterate frames with i < getNumberOfFrames()","Recompute frame counts after loading a new GIF","Never hardcode frame indices"],"tags":["android","index-out-of-bounds","animation"],"backgroundTag":"index-out-of-range","analyzedSha":"26ff795f78b7fe8bbaf375a947b2bda95fc58e3d","analyzedAt":"2026-09-10T14:37:11.595Z","contentChangedAt":"2026-09-10T14:37:11.595Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}