HangfireIO/Hangfire · error · ArgumentOutOfRangeException

threadCount

Error message

threadCount

What it means

Thrown by BackgroundTaskScheduler.DefaultThreadFactory (private) when threadCount is less than or equal to zero. Reached through the public BackgroundTaskScheduler(int threadCount) constructor; threadCount sizes the dedicated thread pool and MaximumConcurrencyLevel, so a non-positive value is invalid.

Source

Thrown at src/Hangfire.Core/Processing/BackgroundTaskScheduler.cs:212

            // Since we want to execute as much tasks as possible on our dedicated threads,
            // we allow to inline only requests from the current scheduler, i.e. just to save
            // some time, since no queueing will be involved.

            if (!_ourThreadIds.Contains(Environment.CurrentManagedThreadId)) return false;

            return TryExecuteTask(task);
        }

        /// <inheritdoc />
        protected override IEnumerable<Task> GetScheduledTasks()
        {
            ThrowIfDisposed();
            return _queue.ToArray();
        }

        private static IEnumerable<Thread> DefaultThreadFactory(ThreadStart threadStart, int threadCount)
        {
            if (threadCount <= 0) throw new ArgumentOutOfRangeException(nameof(threadCount));
            var threads = new Thread[threadCount];

            for (var i = 0; i < threadCount; i++)
            {
                threads[i] = new Thread(threadStart)
                {
                    Name = $"BackgroundThread #{i + 1}",
                    IsBackground = true,
                };
            }

            return threads;
        }

        private static void DefaultExceptionHandler(Exception exception)
        {
#if !NETSTANDARD1_3
            Trace.WriteLine("An unhandled exception occurred: " + exception);

View on GitHub (pinned to c236dd0f93)

Solutions

  1. Pass a threadCount >= 1; prefer Environment.ProcessorCount via the parameterless ctor.
  2. Clamp configured values: `Math.Max(1, configuredCount)`.
  3. Validate config at load time and reject non-positive counts early.

Example fix

// before
var scheduler = new BackgroundTaskScheduler(0);

// after
var scheduler = new BackgroundTaskScheduler(Math.Max(1, Environment.ProcessorCount));
Defensive patterns

Strategy: validation

Validate before calling

int count = Math.Max(1, configuredThreadCount);
var scheduler = new BackgroundTaskScheduler(count);

Try / catch

try { var s = new BackgroundTaskScheduler(configuredCount); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == nameof(configuredCount))
{ configuredCount = Environment.ProcessorCount; /* retry */ }

Prevention

When it happens

Trigger: Calling `new BackgroundTaskScheduler(0)` or with a negative threadCount. Reached when Environment.ProcessorCount is unexpectedly 0 or when a user-supplied concurrency value is non-positive.

Common situations: Config binds WorkerCount/threadCount to 0; a UI allows zero; arithmetic that produces a negative; containerised environment where processor count resolves oddly.

Related errors


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