{"record":{"id":"c0c22153170e7d64","repo":"Intervention/image","slug":"offset-is-not-in-the-range-of-frames-c0c221","errorCode":null,"errorMessage":"Offset is not in the range of frames","messagePattern":"Offset is not in the range of frames","errorType":"validation","errorClass":"Intervention\\Image\\Exceptions\\InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Drivers/Imagick/Modifiers/SliceAnimationModifier.php","lineNumber":20,"sourceCode":"\ndeclare(strict_types=1);\n\nnamespace Intervention\\Image\\Drivers\\Imagick\\Modifiers;\n\nuse Intervention\\Image\\Exceptions\\InvalidArgumentException;\nuse Intervention\\Image\\Interfaces\\ImageInterface;\nuse Intervention\\Image\\Interfaces\\SpecializedInterface;\nuse Intervention\\Image\\Modifiers\\SliceAnimationModifier as GenericSliceAnimationModifier;\n\nclass SliceAnimationModifier extends GenericSliceAnimationModifier implements SpecializedInterface\n{\n    /**\n     * @throws InvalidArgumentException\n     */\n    public function apply(ImageInterface $image): ImageInterface\n    {\n        if ($this->offset >= $image->count()) {\n            throw new InvalidArgumentException('Offset is not in the range of frames');\n        }\n\n        $image->core()->slice($this->offset, $this->length);\n\n        return $image;\n    }\n}\n","sourceCodeStart":2,"sourceCodeEnd":28,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Drivers/Imagick/Modifiers/SliceAnimationModifier.php#L2-L28","documentation":"InvalidArgumentException thrown by SliceAnimationModifier before any frame is removed: the offset must reference an existing frame, i.e. $offset < $image->count(). Offsets are 0-based frame indexes and the check runs in the Imagick-specialized apply() before core()->slice() executes, so nothing is modified when it fires.","triggerScenarios":"$image->sliceAnimation($offset, $length) with $offset >= frame count: sliceAnimation(5) on a 5-frame GIF (valid indexes are 0-4), any offset >= 1 on a static single-frame image (count() === 1), or slicing again after an earlier sliceAnimation() already reduced the frame count.","commonSituations":"Hard-coded frame offsets after switching to source files with fewer frames; computing offset from user input or metadata without bounds-checking; calling sliceAnimation on non-animated images; chaining slices without accounting for the shrinking stack.","solutions":["Compare offset against $image->count() before calling and clamp or reject","Derive the offset from the actual frame count: $offset = min($offset, $image->count() - 1)","For 'last N frames' semantics compute offset as max(0, $image->count() - $length)","Guard with $image->isAnimated() (or count() > 1) before slicing static images"],"exampleFix":"// before\n$image->sliceAnimation(8, 3); // 5-frame GIF -> InvalidArgumentException\n\n// after\n$offset = min(8, $image->count() - 1);\n$image->sliceAnimation($offset, 3);","handlingStrategy":"validation","validationCode":"if ($offset < 0 || $offset >= $image->count()) {\n    throw new InvalidArgumentException(sprintf(\n        'Slice offset %d is outside 0..%d for this image',\n        $offset,\n        max(0, $image->count() - 1)\n    ));\n}\n$image->sliceAnimation($offset, $length);","typeGuard":"function isValidSliceOffset(int $offset, ImageInterface $image): bool\n{\n    return $offset >= 0 && $offset < $image->count();\n}","tryCatchPattern":null,"preventionTips":["Always derive offsets from $image->count(), never hard-code them","Remember count() shrinks after every sliceAnimation call","Branch on $image->isAnimated() before any frame-slicing logic"],"tags":["animation","gif","frames","argument-validation","imagick"],"backgroundTag":"index-out-of-bounds","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}