HangfireIO/Hangfire · error · ArgumentNullException
threadFactory
Error message
threadFactory
What it means
Thrown as ArgumentNullException by the BackgroundDispatcher constructor when the 'threadFactory' Func<ThreadStart, IEnumerable<Thread>> argument is null. BackgroundDispatcher is an internal worker that spawns one or more threads to run the dispatch loop; the threadFactory is the only way to create those threads, so a null factory aborts construction at line 45.
Source
Thrown at src/Hangfire.Core/Processing/BackgroundDispatcher.cs:45
namespace Hangfire.Processing
{
internal sealed class BackgroundDispatcher : IBackgroundDispatcher
{
private readonly ILog _logger = LogProvider.GetLogger(typeof(BackgroundDispatcher));
private readonly CountdownEvent _stopped;
private readonly IBackgroundExecution _execution;
private readonly Action<Guid, object> _action;
private readonly object _state;
public BackgroundDispatcher(
[NotNull] IBackgroundExecution execution,
[NotNull] Action<Guid, object> action,
[CanBeNull] object state,
[NotNull] Func<ThreadStart, IEnumerable<Thread>> threadFactory)
{
if (threadFactory == null) throw new ArgumentNullException(nameof(threadFactory));
_execution = execution ?? throw new ArgumentNullException(nameof(execution));
_action = action ?? throw new ArgumentNullException(nameof(action));
_state = state;
#if !NETSTANDARD1_3
AppDomainUnloadMonitor.EnsureInitialized();
#endif
var threads = threadFactory(DispatchLoop)?.ToArray();
if (threads == null || threads.Length == 0)
{
throw new ArgumentException("At least one unstarted thread should be created.", nameof(threadFactory));
}
if (threads.Any(static thread => thread == null || (thread.ThreadState & ThreadState.Unstarted) == 0))
{View on GitHub (pinned to c236dd0f93)
Solutions
- If you maintain a custom processing server, supply a non-null threadFactory (e.g. start => new[] { new Thread(start) { IsBackground = true } }).
- Use the public BackgroundJobServer API instead of constructing internal dispatchers directly, so the factory is provided for you.
- Ensure any test helper that builds a BackgroundDispatcher passes a valid factory that returns unstarted threads.
Example fix
// before
var d = new BackgroundDispatcher(execution, action, state, null);
// after
Func<ThreadStart, IEnumerable<Thread>> factory =
start => new[] { new Thread(start) { IsBackground = true } };
var d = new BackgroundDispatcher(execution, action, state, factory); Defensive patterns
Strategy: validation
Validate before calling
if (threadFactory == null) throw new ArgumentNullException(nameof(threadFactory));
Func<ThreadStart, IEnumerable<Thread>> factory =
start => new[] { new Thread(start) { IsBackground = true } }; Prevention
- Use the public BackgroundJobServer API instead of constructing internal dispatchers.
- In custom servers/tests, always supply a factory that returns at least one unstarted thread.
When it happens
Trigger: Constructing a BackgroundDispatcher with a null threadFactory. This is an internal API normally invoked by the Hangfire processing machinery (BackgroundJobServer/processing server) with a framework-supplied factory; a null factory would only arise from a custom/derived processing server or a reflection-based instantiation that did not supply one.
Common situations: A custom processing server that manually instantiates BackgroundDispatcher with a null factory; a test that constructs the dispatcher without a thread factory; a reflection/serialization path that omits the argument. End users of BackgroundJobServer do not pass this argument directly.
Related errors
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/319a4981cab5034b.
Report an issue: GitHub.