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
- Pass a threadCount >= 1; prefer Environment.ProcessorCount via the parameterless ctor.
- Clamp configured values: `Math.Max(1, configuredCount)`.
- 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
- Clamp thread counts to >= 1 at the configuration boundary.
- Prefer the parameterless ctor (uses Environment.ProcessorCount).
- Reject zero/negative counts in config validation.
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
- maxConcurrency
- threadFactory
- At least one non-started thread should be created.
- All the threads should be non-null and in the ThreadState.Un
- All the threads should be non-null and in the ThreadState.Un
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/5ece49b8f5bfdb0e.
Report an issue: GitHub.