{"record":{"id":"9e9100d100e16708","repo":"devlooped/moq","slug":"delays-have-to-be-greater-than-zero-to-ensure-an-async","errorCode":null,"errorMessage":"Delays have to be greater than zero to ensure an async callback is used.","messagePattern":"Delays have to be greater than zero to ensure an async callback is used\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Moq/Guard.cs","lineNumber":223,"sourceCode":"                        memberAccess.ToStringFixed()));\n        }\n\n        public static void IsMockable(Type type)\n        {\n            if (!type.IsMockable())\n            {\n                throw new NotSupportedException(\n                    string.Format(\n                        Resources.TypeNotMockable,\n                        type.GetFormattedName()));\n            }\n        }\n\n        public static void Positive(TimeSpan delay)\n        {\n            if (delay <= TimeSpan.Zero)\n            {\n                throw new ArgumentException(Resources.DelaysMustBeGreaterThanZero);\n            }\n        }\n\n        public static void CanRead(PropertyInfo property)\n        {\n            if (!property.CanRead(out _))\n            {\n                throw new ArgumentException(string.Format(\n                    CultureInfo.CurrentCulture,\n                    Resources.PropertyGetNotFound,\n                    property.DeclaringType!.Name, property.Name));\n            }\n        }\n\n        public static void CanWrite(PropertyInfo property)\n        {\n            if (!property.CanWrite(out _))\n            {","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/devlooped/moq/blob/89a5be629c752960fe403e95ff583e4ae6f00542/src/Moq/Guard.cs#L205-L241","documentation":"This ArgumentException from Guard.Positive enforces that a delay passed to Moq's async/timing APIs (e.g. Mock.Of/Delays inside SetupSequence or ReturnsAsync delay overloads, via Moq's Delay/Timeout features) is strictly greater than TimeSpan.Zero. A zero or negative delay cannot guarantee the async callback machinery is used.","triggerScenarios":"Passing TimeSpan.Zero or a negative TimeSpan to an API whose guard is Guard.Positive(TimeSpan), such as delay-based callback/Returns overloads used with async setups.","commonSituations":"Computing a delay from config that resolves to 0; sign errors making the TimeSpan negative; default TimeSpan values (TimeSpan.Zero) passed through unmodified.","solutions":["Pass a strictly positive TimeSpan, e.g. TimeSpan.FromMilliseconds(1) or greater.","Validate/normalize configured delay values before calling the API (clamp to a minimum of 1ms).","If you truly need no delay, use the non-delayed overload of the API instead of passing zero."],"exampleFix":"// before\nmock.SetupSequence(m => m.Load()).ReturnsAsync(data, TimeSpan.Zero);\n// after\nmock.SetupSequence(m => m.Load()).ReturnsAsync(data, TimeSpan.FromMilliseconds(50));","handlingStrategy":"validation","validationCode":"if (delay <= TimeSpan.Zero)\n    throw new ArgumentException(\"Delay must be positive before calling Moq delay APIs\");\n","typeGuard":"static bool IsPositiveDelay(TimeSpan d) => d > TimeSpan.Zero;\n","tryCatchPattern":"try { api.WithDelay(delay); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Delays\"))\n{\n    delay = TimeSpan.FromMilliseconds(1); // retry with minimal positive delay\n}\n","preventionTips":["Never pass TimeSpan.Zero or default(TimeSpan) to delay parameters","Clamp configured delays to a minimum positive value","Check sign of computed/subtracted TimeSpans before use"],"tags":["moq","argument-out-of-range","timespan","async"],"backgroundTag":"argument-out-of-range","analyzedSha":"89a5be629c752960fe403e95ff583e4ae6f00542","analyzedAt":"2026-09-16T05:31:39.496Z","contentChangedAt":"2026-09-16T05:31:39.496Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}