HangfireIO/Hangfire · error · ArgumentOutOfRangeException

Value should be greater than or equal to TimeSpan.Zero

Error message

Value should be greater than or equal to TimeSpan.Zero

What it means

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.

Source

Thrown at src/Hangfire.Core/Processing/BackgroundExecutionOptions.cs:43

        private TimeSpan _stillErrorThreshold;
        private Func<int, TimeSpan> _retryDelay;

        public BackgroundExecutionOptions()
        {
            WarningThreshold = TimeSpan.FromSeconds(5);
            ErrorThreshold = TimeSpan.FromSeconds(15);
            StillErrorThreshold = TimeSpan.FromSeconds(60);
            RetryDelay = GetBackOffMultiplier;
        }

        public string Name { get; set; }

        public TimeSpan WarningThreshold
        {
            get { return _warningThreshold; }
            set
            {
                if (value < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(value), "Value should be greater than or equal to TimeSpan.Zero");
                _warningThreshold = value;
            }
        }

        public TimeSpan ErrorThreshold
        {
            get { return _errorThreshold; }
            set
            {
                if (value < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(value), "Value should be greater than or equal to TimeSpan.Zero");
                _errorThreshold = value;
            }
        }

        public TimeSpan StillErrorThreshold
        {
            get { return _stillErrorThreshold; }
            set

View on GitHub (pinned to c236dd0f93)

Solutions

  1. Clamp the value before assignment: `options.WarningThreshold = TimeSpan.FromMilliseconds(Math.Max(0, value.TotalMilliseconds))`.
  2. Validate parsed config at the boundary and reject/replace negative values with a sane default.
  3. Default is 5s — only override with a known non-negative value.

Example fix

// before
options.WarningThreshold = parsedDelay; // parsedDelay == TimeSpan.FromSeconds(-5)

// after
options.WarningThreshold = parsedDelay < TimeSpan.Zero ? TimeSpan.FromSeconds(5) : parsedDelay;
Defensive patterns

Strategy: validation

Validate before calling

TimeSpan Safe(TimeSpan v) => v < TimeSpan.Zero ? TimeSpan.FromSeconds(5) : v;
options.WarningThreshold = Safe(parsedDelay);

Type guard

static bool IsValidThreshold(TimeSpan v) => v >= TimeSpan.Zero;

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13). Data as JSON: /api/errors/9f752ba594256bc9. Report an issue: GitHub.