{"record":{"id":"86557f16fd5cde38","repo":"daimajia/AndroidViewAnimations","slug":"can-not-be-less-than-1-1-is-infinite-loop","errorCode":null,"errorMessage":"Can not be less than -1, -1 is infinite loop","messagePattern":"Can not be less than -1, -1 is infinite loop","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/daimajia/androidanimations/library/YoYo.java","lineNumber":156,"sourceCode":"        public AnimationComposer pivot(float pivotX, float pivotY) {\n            this.pivotX = pivotX;\n            this.pivotY = pivotY;\n            return this;\n        }\n\n        public AnimationComposer pivotX(float pivotX) {\n            this.pivotX = pivotX;\n            return this;\n        }\n\n        public AnimationComposer pivotY(float pivotY) {\n            this.pivotY = pivotY;\n            return this;\n        }\n\n        public AnimationComposer repeat(int times) {\n            if (times < INFINITE) {\n                throw new RuntimeException(\"Can not be less than -1, -1 is infinite loop\");\n            }\n            repeat = times != 0;\n            repeatTimes = times;\n            return this;\n        }\n\n        public AnimationComposer repeatMode(int mode) {\n            repeatMode = mode;\n            return this;\n        }\n\n        public AnimationComposer withListener(Animator.AnimatorListener listener) {\n            callbacks.add(listener);\n            return this;\n        }\n\n        public AnimationComposer onStart(final AnimatorCallback callback) {\n            callbacks.add(new EmptyAnimatorListener() {","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/daimajia/AndroidViewAnimations/blob/6a35c466d23e49c5cd174289ebe8d9ccdbc69044/library/src/main/java/com/daimajia/androidanimations/library/YoYo.java#L138-L174","documentation":"AnimationComposer.repeat(int times) validates the loop-count argument at composition time: the minimum legal value is INFINITE (-1), which means loop forever. Any value below -1 (e.g. -2) is rejected with a RuntimeException because there is no meaningful repeat count less than infinite; 0 means play once (repeat disabled), positive values repeat that many times.","triggerScenarios":"Calling YoYo.with(...).repeat(n) with n < -1 — typically a computed count that drifted negative (e.g. repeat(count - 2) when count <= 1), a misdecoded remote-config value, or confusing -1 semantics with other negative sentinels.","commonSituations":"Passing user-supplied or server-supplied repeat counts without clamping; off-by-one arithmetic on repeat counters; developers using negative values as 'disabled' flags instead of 0.","solutions":["Clamp before calling: pass Math.max(-1, times) or map any negative to INFINITE (-1)","If you want a single playthrough, pass 0 or omit repeat(); only -1 means infinite","Validate the count at its source (user input/API payload) and normalize there","If the count is untrusted, wrap the composer chain in try-catch and fall back to a sane default like repeat(1)"],"exampleFix":"// before\nint times = serverConfig.getRepeatCount(); // may be -3\nYoYo.with(Techniques.Bounce).repeat(times).playOn(view);\n// after\nint times = serverConfig.getRepeatCount();\nif (times < -1) times = -1; // INFINITE\nYoYo.with(Techniques.Bounce).repeat(times).playOn(view);","handlingStrategy":"validation","validationCode":"static int safeRepeat(int times) {\n    final int INFINITE = -1;\n    if (times < INFINITE) {\n        throw new IllegalArgumentException(\"repeat must be >= -1 (INFINITE), got \" + times);\n    }\n    return times;\n}\n// usage: YoYo.with(Techniques.Tada).repeat(safeRepeat(userCount)).playOn(view);","typeGuard":null,"tryCatchPattern":"try {\n    YoYo.with(Techniques.Bounce).repeat(times).playOn(view);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"less than -1\")) {\n        Log.w(\"YoYo\", \"bad repeat count \" + times + \", using default\");\n        YoYo.with(Techniques.Bounce).repeat(1).playOn(view);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Clamp any computed or externally supplied repeat count to >= -1 before calling repeat()","Remember the semantics: 0 = play once, -1 = infinite, positive n = repeat n times","Unit-test composition code with edge inputs (0, -1, -2) to catch off-by-one errors early","Centralize repeat-count parsing/normalization in one helper instead of inlining raw values"],"tags":["validation","argument-out-of-range","android","animation"],"backgroundTag":"argument-out-of-range","analyzedSha":"6a35c466d23e49c5cd174289ebe8d9ccdbc69044","analyzedAt":"2026-09-08T03:31:43.217Z","contentChangedAt":"2026-09-08T03:31:43.217Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}