{"record":{"id":"e3a2706ed4ca18dc","repo":"Cysharp/UniTask","slug":"delay-does-not-allow-minus-periodframecount-perio","errorCode":null,"errorMessage":"Delay does not allow minus periodFrameCount. periodFrameCount:","messagePattern":"Delay does not allow minus periodFrameCount\\. periodFrameCount:","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/UnityExtensions/Timer.cs","lineNumber":42,"sourceCode":"        public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)\n        {\n            if (dueTimeFrameCount < 0)\n            {\n                throw new ArgumentOutOfRangeException(\"Delay does not allow minus delayFrameCount. dueTimeFrameCount:\" + dueTimeFrameCount);\n            }\n\n            return new TimerFrame(dueTimeFrameCount, null, updateTiming, cancelImmediately);\n        }\n\n        public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)\n        {\n            if (dueTimeFrameCount < 0)\n            {\n                throw new ArgumentOutOfRangeException(\"Delay does not allow minus delayFrameCount. dueTimeFrameCount:\" + dueTimeFrameCount);\n            }\n            if (periodFrameCount < 0)\n            {\n                throw new ArgumentOutOfRangeException(\"Delay does not allow minus periodFrameCount. periodFrameCount:\" + dueTimeFrameCount);\n            }\n\n            return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancelImmediately);\n        }\n\n        public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)\n        {\n            if (intervalFrameCount < 0)\n            {\n                throw new ArgumentOutOfRangeException(\"Delay does not allow minus intervalFrameCount. intervalFrameCount:\" + intervalFrameCount);\n            }\n            return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming, cancelImmediately);\n        }\n    }\n\n    internal class Timer : IUniTaskAsyncEnumerable<AsyncUnit>\n    {\n        readonly PlayerLoopTiming updateTiming;","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/Cysharp/UniTask/blob/ceac8d6946b1125fe782cd171fbcb245b567dbf9/src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/UnityExtensions/Timer.cs#L24-L60","documentation":"Thrown by the two-parameter TimerFrame overload when periodFrameCount is negative. NOTE: there is a bug in the error message — the code interpolates dueTimeFrameCount instead of periodFrameCount (line 42: `\"periodFrameCount:\" + dueTimeFrameCount`). So the thrown message will display the wrong variable's value, which can mislead debugging. The check itself correctly tests periodFrameCount < 0.","triggerScenarios":"Passing negative periodFrameCount to TimerFrame(dueTimeFrameCount, periodFrameCount, ...). The due time is checked first, so this only fires if dueTimeFrameCount is valid (>= 0) but periodFrameCount is negative.","commonSituations":"Setting up a repeating frame timer with a bad period value. Using -1 as a 'no period' sentinel instead of passing null (the single-parameter overload). Copy-paste error in parameter passing.","solutions":["Validate/clamp periodFrameCount: var period = Math.Max(0, periodFrameCount); before calling TimerFrame.","If you want a non-repeating timer, use the single-parameter TimerFrame(dueTimeFrameCount) overload instead of passing a negative period.","Be aware the error message shows dueTimeFrameCount's value due to a source bug — check the periodFrameCount argument you passed."],"exampleFix":"// before\nawait UniTaskAsyncEnumerable.TimerFrame(5, -1).ForEachAwaitAsync(_ => { });\n// throws: 'periodFrameCount: 5' (misleading due to source bug)\n\n// after (non-repeating timer)\nawait UniTaskAsyncEnumerable.TimerFrame(5).ForEachAwaitAsync(_ => { });","handlingStrategy":"validation","validationCode":"var safePeriod = Math.Max(0, periodFrameCount);\nawait UniTaskAsyncEnumerable.TimerFrame(dueTimeFrameCount, safePeriod).ForEachAwaitAsync(_ => { });\n// NOTE: The error message has a bug — it prints dueTimeFrameCount's value\n// instead of periodFrameCount. Check the period argument you actually passed.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp periodFrameCount to >= 0 before calling the two-parameter TimerFrame.","If you want a non-repeating timer, use the single-parameter TimerFrame overload instead of a negative period.","Be aware of the misleading error message — inspect the periodFrameCount argument, not the displayed value."],"tags":["timer","frame-based","argument-validation","repeating","bug-in-message"],"backgroundTag":null,"analyzedSha":"ceac8d6946b1125fe782cd171fbcb245b567dbf9","analyzedAt":"2026-08-13T19:16:39.025Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}