{"record":{"id":"f17960e6d8e6cf91","repo":"Yalantis/uCrop","slug":"animation-duration-cannot-be-negative-value","errorCode":null,"errorMessage":"Animation duration cannot be negative value.","messagePattern":"Animation duration cannot be negative value\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"ucrop/src/main/java/com/yalantis/ucrop/view/CropImageView.java","lineNumber":187,"sourceCode":"    /**\n     * This method sets maximum width for resulting cropped image\n     *\n     * @param maxResultImageSizeY - size in pixels\n     */\n    public void setMaxResultImageSizeY(@IntRange(from = 10) int maxResultImageSizeY) {\n        mMaxResultImageSizeY = maxResultImageSizeY;\n    }\n\n    /**\n     * This method sets animation duration for image to wrap the crop bounds\n     *\n     * @param imageToWrapCropBoundsAnimDuration - duration in milliseconds\n     */\n    public void setImageToWrapCropBoundsAnimDuration(@IntRange(from = 100) long imageToWrapCropBoundsAnimDuration) {\n        if (imageToWrapCropBoundsAnimDuration > 0) {\n            mImageToWrapCropBoundsAnimDuration = imageToWrapCropBoundsAnimDuration;\n        } else {\n            throw new IllegalArgumentException(\"Animation duration cannot be negative value.\");\n        }\n    }\n\n    /**\n     * This method sets multiplier that is used to calculate max image scale from min image scale.\n     *\n     * @param maxScaleMultiplier - (minScale * maxScaleMultiplier) = maxScale\n     */\n    public void setMaxScaleMultiplier(float maxScaleMultiplier) {\n        mMaxScaleMultiplier = maxScaleMultiplier;\n    }\n\n    /**\n     * This method scales image down for given value related to image center.\n     */\n    public void zoomOutImage(float deltaScale) {\n        zoomOutImage(deltaScale, mCropRect.centerX(), mCropRect.centerY());\n    }","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/Yalantis/uCrop/blob/f788b534b48c144edf786c8cddbf0e029e637804/ucrop/src/main/java/com/yalantis/ucrop/view/CropImageView.java#L169-L205","documentation":"CropImageView.setImageToWrapCropBoundsAnimDuration only accepts durations > 0; passing 0 or a negative value throws this IllegalArgumentException despite the message only mentioning negative values (the annotation also demands a minimum of 100 ms). It controls the animation that snaps the image to wrap the crop bounds after gestures.","triggerScenarios":"Calling setImageToWrapCropBoundsAnimDuration(0) or with any negative long; passing an uninitialized/unparsed duration variable that defaulted to 0.","commonSituations":"Reading a duration from config/preferences where the key is missing (parsed as 0); passing a constant meant for another API where 0 means 'no animation'; copy-pasting a duration in the wrong unit and truncating to 0.","solutions":["Pass a positive value; use the default if you don't need customization.","Clamp the incoming duration: Math.max(100, configuredDuration).","If your source value may be 0/unset, guard it and only call the setter when > 0.","Follow the @IntRange(from = 100) contract: prefer durations of at least 100 ms so the animation is visible."],"exampleFix":"// before\ncropImageView.setImageToWrapCropBoundsAnimDuration(prefs.getInt(\"anim_duration\", 0));\n// after\nlong duration = Math.max(100, prefs.getInt(\"anim_duration\", 300));\ncropImageView.setImageToWrapCropBoundsAnimDuration(duration);","handlingStrategy":"validation","validationCode":"long safeDuration = configuredDurationMs > 0 ? Math.max(100, configuredDurationMs) : 300;\ncropImageView.setImageToWrapCropBoundsAnimDuration(safeDuration);","typeGuard":"boolean isValidAnimDuration(long durationMs) { return durationMs >= 100; }","tryCatchPattern":"try {\n    cropImageView.setImageToWrapCropBoundsAnimDuration(duration);\n} catch (IllegalArgumentException e) {\n    cropImageView.setImageToWrapCropBoundsAnimDuration(300); // default\n}","preventionTips":["Never pass 0 expecting 'disable animation' — the API requires a positive duration.","Default missing config values to a sane positive constant (e.g. 300 ms).","Honor the @IntRange(from = 100) annotation: prefer >= 100 ms.","Clamp user/config-supplied durations with Math.max(100, value)."],"tags":["android","ucrop","animation","duration","illegal-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"f788b534b48c144edf786c8cddbf0e029e637804","analyzedAt":"2026-09-08T08:36:04.887Z","contentChangedAt":"2026-09-08T08:36:04.887Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}