HangfireIO/Hangfire · error · ArgumentOutOfRangeException

SchedulePollingInterval must be non-negative and either…

Error message

SchedulePollingInterval must be non-negative and either equal to or less than {Int32.MaxValue} milliseconds

What it means

This ArgumentOutOfRangeException("value", "SchedulePollingInterval must be non-negative and either equal to or less than Int32.MaxValue milliseconds") is thrown by the SchedulePollingInterval setter of BackgroundJobServerOptions. Unlike the timeouts, this setter does NOT accept Timeout.InfiniteTimeSpan as a special case (any negative value is rejected) and rejects values over Int32.MaxValue total milliseconds. The interval governs how often the DelayedJobScheduler polls storage for due delayed jobs.

Solutions

  1. Use a non-negative TimeSpan within Int32.MaxValue ms (the default is DelayedJobScheduler.DefaultPollingDelay, 15s).
  2. To effectively disable polling on a lightweight server, set IsLightweightServer = true instead of an infinite interval.
  3. Clamp the bound value into the legal range.
  4. Validate the configured value at startup.

Example fix

// before
options.SchedulePollingInterval = Timeout.InfiniteTimeSpan; // rejected

// after
options.IsLightweightServer = true; // excludes the delayed-job scheduler entirely
Defensive patterns

Strategy: validation

Validate before calling

TimeSpan SanitizeInterval(TimeSpan ts) =>
    ts >= TimeSpan.Zero && ts.TotalMilliseconds <= int.MaxValue ? ts : DelayedJobScheduler.DefaultPollingDelay;
options.SchedulePollingInterval = SanitizeInterval(parsed);

Type guard

static bool IsValidInterval(TimeSpan ts) => ts >= TimeSpan.Zero && ts.TotalMilliseconds <= int.MaxValue;

Try / catch

try { options.SchedulePollingInterval = parsed; }
catch (ArgumentOutOfRangeException) { options.SchedulePollingInterval = DelayedJobScheduler.DefaultPollingDelay; }

Prevention

When it happens

Trigger: Assigning options.SchedulePollingInterval = TimeSpan.FromSeconds(-1); assigning Timeout.InfiniteTimeSpan (rejected here, unlike timeouts); assigning a TimeSpan whose total milliseconds exceed Int32.MaxValue.

Common situations: Attempting to disable delayed-job polling by setting the interval to Timeout.InfiniteTimeSpan (not allowed); config typos; unit confusion; binding a huge or negative value from configuration.

Related errors


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

Appendix: source

Thrown at src/Hangfire.Core/BackgroundJobServerOptions.cs:123

            get { return _shutdownTimeout; }
            set
            {
                if ((value < TimeSpan.Zero && value != Timeout.InfiniteTimeSpan) || value.TotalMilliseconds > Int32.MaxValue)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), $"ShutdownTimeout must be either equal to or less than {Int32.MaxValue} milliseconds and non-negative or infinite");
                }
                _shutdownTimeout = value;
            }
        }

        public TimeSpan SchedulePollingInterval
        {
            get { return _schedulePollingInterval; }
            set
            {
                if (value < TimeSpan.Zero || value.TotalMilliseconds > Int32.MaxValue)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), $"SchedulePollingInterval must be non-negative and either equal to or less than {Int32.MaxValue} milliseconds");
                }

                _schedulePollingInterval = value;
            }
        }

        public TimeSpan HeartbeatInterval
        {
            get { return _heartbeatInterval; }
            set
            {
                if (value < TimeSpan.Zero || value > ServerWatchdog.MaxHeartbeatInterval)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), $"HeartbeatInterval must be either non-negative and equal to or less than {ServerWatchdog.MaxHeartbeatInterval.Hours} hours");
                }
                _heartbeatInterval = value;
            }
        }

View on GitHub (pinned to c236dd0f93)