{"record":{"id":"8548f1b9a9d6b8f9","repo":"louthy/language-ext","slug":"milliseconds-must-be-a-positive-number","errorCode":null,"errorMessage":"milliseconds must be a positive number.","messagePattern":"milliseconds must be a positive number\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"LanguageExt.Core/Effects/Schedule/Duration.cs","lineNumber":24,"sourceCode":"\n/// <summary>\n/// Period of time in milliseconds.\n/// Can be used to convert between other duration like types, such as TimeSpan and Time.\n/// </summary>\npublic readonly struct Duration :\n    IEquatable<Duration>,\n    IComparable<Duration>\n{\n    public readonly double Milliseconds;\n\n    /// <summary>\n    /// Duration constructor\n    /// </summary>\n    /// <param name=\"milliseconds\">Magnitude of the duration.  Must be zero or a positive value</param>\n    /// <exception cref=\"ArgumentException\">Throws if `milliseconds` is less than `0`</exception>\n    public Duration(double milliseconds)\n    {\n        if (milliseconds < 0) throw new ArgumentException($\"{nameof(milliseconds)} must be a positive number.\");\n        Milliseconds = milliseconds;\n    }\n\n    /// <summary>\n    /// Zero magnitude duration (instant)\n    /// </summary>\n    public static Duration Zero =\n        new(0);\n    \n    /// <summary>\n    /// Return true if the time duration is zero\n    /// </summary>\n    public bool IsZero =>\n        Milliseconds < 0.00000000001;\n\n    /// <summary>\n    /// Random duration between the provided min and max durations. \n    /// </summary>","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/louthy/language-ext/blob/2f0e3628242889774d4141960a35671a0280051f/LanguageExt.Core/Effects/Schedule/Duration.cs#L6-L42","documentation":"The Duration(double milliseconds) constructor validates that the magnitude is non-negative and throws ArgumentException with the message \"milliseconds must be a positive number.\" if the value is below 0. LanguageExt schedules cannot represent negative (past) durations.","triggerScenarios":"new Duration(-1), passing a negative computed interval (e.g. endTime - startTime where start > end), or subtracting delays that underflow into negative values when building a Schedule.","commonSituations":"Computing retry backoff from timestamps where clocks are out of order, parsing config values that may be negative, or subtracting elapsed from remaining time that has already gone negative.","solutions":["Clamp the computed value: Math.Max(0, milliseconds) before constructing Duration.","Fix the calculation producing the negative interval (ordering of timestamps).","Validate config/inputs so negative delays are rejected or coerced earlier."],"exampleFix":"// before\nvar d = new Duration(next - prev);\n// after\nvar d = new Duration(Math.Max(0, next - prev));","handlingStrategy":"validation","validationCode":"if (milliseconds < 0) throw new ArgumentOutOfRangeException(nameof(milliseconds));\nvar d = new Duration(Math.Max(0, milliseconds));","typeGuard":"static bool IsValidDuration(double ms) => !double.IsNaN(ms) && ms >= 0;","tryCatchPattern":"try { var d = new Duration(ms); } catch (ArgumentException e) { /* negative duration */ }","preventionTips":["Clamp computed intervals with Math.Max(0, ...)","Validate timestamp ordering before subtracting","Sanitize configured delay values"],"tags":["schedule","duration","argument"],"backgroundTag":"argument-out-of-range","analyzedSha":"2f0e3628242889774d4141960a35671a0280051f","analyzedAt":"2026-09-15T03:31:55.716Z","contentChangedAt":"2026-09-15T03:31:55.716Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}