{"record":{"id":"44857f23045061d7","repo":"Cysharp/UniTask","slug":"delay-does-not-allow-minus-delayframecount-duetim","errorCode":null,"errorMessage":"Delay does not allow minus delayFrameCount. dueTimeFrameCount:","messagePattern":"Delay does not allow minus delayFrameCount\\. dueTimeFrameCount:","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/UnityExtensions/Timer.cs","lineNumber":28,"sourceCode":"        {\n            return new Timer(dueTime, null, updateTiming, ignoreTimeScale, cancelImmediately);\n        }\n\n        public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)\n        {\n            return new Timer(dueTime, period, updateTiming, ignoreTimeScale, cancelImmediately);\n        }\n\n        public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)\n        {\n            return new Timer(period, period, updateTiming, ignoreTimeScale, cancelImmediately);\n        }\n\n        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        }","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/Cysharp/UniTask/blob/ceac8d6946b1125fe782cd171fbcb245b567dbf9/src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/UnityExtensions/Timer.cs#L10-L46","documentation":"Thrown by the single-parameter TimerFrame(dueTimeFrameCount) when dueTimeFrameCount is negative. A negative frame delay is meaningless — it implies firing the timer before the current frame. This is a standard precondition check on the public API.","triggerScenarios":"Passing a computed or user-supplied negative integer to UniTaskAsyncEnumerable.TimerFrame(dueTimeFrameCount). E.g., a calculated delay based on a target frame that has already passed.","commonSituations":"Scheduling a frame-based timer relative to a past frame count. An arithmetic underflow in computing the delay. Dynamic scheduling from serialized data with bad values.","solutions":["Clamp the value: var frames = Math.Max(0, dueTimeFrameCount); before calling TimerFrame.","Fix the upstream calculation that produced the negative frame count."],"exampleFix":"// before\nvar delay = targetFrame - Time.frameCount;\nawait UniTaskAsyncEnumerable.TimerFrame(delay).ForEachAwaitAsync(_ => { }); // throws if targetFrame already passed\n\n// after\nvar delay = Math.Max(0, targetFrame - Time.frameCount);\nawait UniTaskAsyncEnumerable.TimerFrame(delay).ForEachAwaitAsync(_ => { });","handlingStrategy":"validation","validationCode":"var safeFrames = Math.Max(0, dueTimeFrameCount);\nawait UniTaskAsyncEnumerable.TimerFrame(safeFrames).ForEachAwaitAsync(_ => { });","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always clamp frame counts with Math.Max(0, value) before passing to TimerFrame.","Validate dynamic/computed frame delays at the source rather than at the API boundary."],"tags":["timer","frame-based","argument-validation"],"backgroundTag":null,"analyzedSha":"ceac8d6946b1125fe782cd171fbcb245b567dbf9","analyzedAt":"2026-08-13T19:16:39.025Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}