{"record":{"id":"9f752ba594256bc9","repo":"HangfireIO/Hangfire","slug":"value-should-be-greater-than-or-equal-to-timespan","errorCode":null,"errorMessage":"Value should be greater than or equal to TimeSpan.Zero","messagePattern":"Value should be greater than or equal to TimeSpan\\.Zero","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.Core/Processing/BackgroundExecutionOptions.cs","lineNumber":43,"sourceCode":"        private TimeSpan _stillErrorThreshold;\n        private Func<int, TimeSpan> _retryDelay;\n\n        public BackgroundExecutionOptions()\n        {\n            WarningThreshold = TimeSpan.FromSeconds(5);\n            ErrorThreshold = TimeSpan.FromSeconds(15);\n            StillErrorThreshold = TimeSpan.FromSeconds(60);\n            RetryDelay = GetBackOffMultiplier;\n        }\n\n        public string Name { get; set; }\n\n        public TimeSpan WarningThreshold\n        {\n            get { return _warningThreshold; }\n            set\n            {\n                if (value < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(value), \"Value should be greater than or equal to TimeSpan.Zero\");\n                _warningThreshold = value;\n            }\n        }\n\n        public TimeSpan ErrorThreshold\n        {\n            get { return _errorThreshold; }\n            set\n            {\n                if (value < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(value), \"Value should be greater than or equal to TimeSpan.Zero\");\n                _errorThreshold = value;\n            }\n        }\n\n        public TimeSpan StillErrorThreshold\n        {\n            get { return _stillErrorThreshold; }\n            set","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.Core/Processing/BackgroundExecutionOptions.cs#L25-L61","documentation":"Thrown by the BackgroundExecutionOptions.WarningThreshold setter (internal) when the assigned TimeSpan is less than TimeSpan.Zero. WarningThreshold governs when Faulted-state recovery is logged at Info vs Debug, so a negative span is invalid.","triggerScenarios":"Assigning options.WarningThreshold to a negative TimeSpan. Reached when configuration parsing produces a negative duration (e.g., parsing a malformed '-5s' string or subtracting offsets).","commonSituations":"A config binding that maps an empty/invalid string to a negative TimeSpan; arithmetic that subtracts two thresholds and underflows; serialisation round-trip that lost the value.","solutions":["Clamp the value before assignment: `options.WarningThreshold = TimeSpan.FromMilliseconds(Math.Max(0, value.TotalMilliseconds))`.","Validate parsed config at the boundary and reject/replace negative values with a sane default.","Default is 5s — only override with a known non-negative value."],"exampleFix":"// before\noptions.WarningThreshold = parsedDelay; // parsedDelay == TimeSpan.FromSeconds(-5)\n\n// after\noptions.WarningThreshold = parsedDelay < TimeSpan.Zero ? TimeSpan.FromSeconds(5) : parsedDelay;","handlingStrategy":"validation","validationCode":"TimeSpan Safe(TimeSpan v) => v < TimeSpan.Zero ? TimeSpan.FromSeconds(5) : v;\noptions.WarningThreshold = Safe(parsedDelay);","typeGuard":"static bool IsValidThreshold(TimeSpan v) => v >= TimeSpan.Zero;","tryCatchPattern":null,"preventionTips":["Clamp all parsed TimeSpans to >= Zero at the config boundary.","Reject negative durations in any UI that edits thresholds.","Keep the default (5s) unless you have a measured reason to change it."],"tags":["hangfire","argument-validation","configuration","timespan","background-processing"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}