HangfireIO/Hangfire · error · ArgumentNullException

callback

Error message

callback

What it means

Thrown by BackgroundExecution.Run (internal) when the synchronous callback Action<Guid, object> is null. Run invokes callback(executionId, state) inside the retry loop, so a null delegate would throw NRE mid-loop.

Source

Thrown at src/Hangfire.Core/Processing/BackgroundExecution.cs:73

            _options = options ?? throw new ArgumentNullException(nameof(options));

            _logger = LogProvider.GetLogger(GetType());
            _createdAt = Stopwatch.StartNew();

            _stopToken = stopToken;

            _stopRegistration = _stopToken.Register(SetStoppedAt);

#if !NETSTANDARD1_3
            AppDomainUnloadMonitor.EnsureInitialized();
#endif
        }

        public bool StopRequested => _disposed || _stopToken.IsCancellationRequested;

        public void Run(Action<Guid, object> callback, object state)
        {
            if (callback == null) throw new ArgumentNullException(nameof(callback));

            var executionId = Guid.NewGuid();

            // ExecutionId is a custom correlation id for logging purposes. We can use Thread's
            // ManagedThreadId property here, but it's better to have a single implementation between
            // sync and async dispatchers - async one can execute related tasks on different threads,
            // so ManagedThreadId doesn't work there.
            //using (LogProvider.OpenMappedContext("ExecutionId", executionId.ToString()))
            {
#if !NETSTANDARD1_3
                try
#endif
                {
                    HandleStarted(executionId, out var nextDelay);

                    // There should be no operations between the `while` and `try` blocks to
                    // avoid unintended stopping due to ThreadAbortException between the loop
                    // iterations. Even loop condition is placed into the `try` block.

View on GitHub (pinned to c236dd0f93)

Solutions

  1. Pass a non-null Action<Guid, object> callback to Run.
  2. Ensure the dispatcher's action delegate is validated at construction (BackgroundDispatcher already checks action for null).
  3. In tests, supply even a no-op callback `(_, __) => { }`.

Example fix

// before
execution.Run(null, state);

// after
execution.Run((id, s) => DoWork(id, s), state);
Defensive patterns

Strategy: validation

Validate before calling

if (callback == null) throw new ArgumentNullException(nameof(callback));
execution.Run(callback, state);

Prevention

When it happens

Trigger: Calling backgroundExecution.Run(null, state). The execution is driven by a dispatcher that passes its _action; if that action delegate was null the error surfaces here.

Common situations: A dispatcher constructed with a null action whose check was bypassed; a test harness calling Run directly with a null lambda; a refactor that left the callback argument empty.

Related errors


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