HangfireIO/Hangfire · error · InvalidOperationException

JobActivator returned NULL instance of the '{context.Backgro

Error message

JobActivator returned NULL instance of the '{context.BackgroundJob.Job.Type}' type.

What it means

Thrown by CoreBackgroundJobPerformer.Perform when the JobActivator scope resolves to null for a non-static job type. Hangfire relies on the activator (DI integration) to construct the job's target class; returning null means the type could not be activated, which is always a configuration/registration problem.

Source

Thrown at src/Hangfire.Core/Server/CoreBackgroundJobPerformer.cs:64

        public object Perform(PerformContext context)
        {
            using (var scope = _activator.BeginScope(context))
            {
                object instance = null;

                if (context.BackgroundJob.Job == null)
                {
                    throw new InvalidOperationException("Can't perform a background job with a null job.");
                }
                
                if (!context.BackgroundJob.Job.Method.IsStatic)
                {
                    instance = scope.Resolve(context.BackgroundJob.Job.Type);

                    if (instance == null)
                    {
                        throw new InvalidOperationException(
                            $"JobActivator returned NULL instance of the '{context.BackgroundJob.Job.Type}' type.");
                    }
                }

                var arguments = SubstituteArguments(context);
                var result = InvokeMethod(context, instance, arguments);

                return result;
            }
        }

        internal static void HandleJobPerformanceException(Exception exception, IJobCancellationToken cancellationToken, [CanBeNull] BackgroundJob job)
        {
            if (exception is JobAbortedException)
            {
                // JobAbortedException exception should be thrown as-is to notify
                // a worker that background job was aborted by a state change, and
                // should NOT be re-queued.

View on GitHub (pinned to c236dd0f93)

Solutions

  1. Register the job's type in the DI container that backs the JobActivator (e.g. services.AddTransient<MyJob>() in ASP.NET Core).
  2. Ensure the resolved type matches the type referenced in the job expression exactly.
  3. Use a JobActivator that can create the type, or make the method static if no instance is needed.

Example fix

// before
public class MyJob { public void Run() { } }
// MyJob not registered → JobActivator returns null

// after
// Startup.cs / Program.cs
services.AddTransient<MyJob>();
Defensive patterns

Strategy: validation

Validate before calling

// At startup, verify the job type is registered with the DI container backing the activator
var sp = app.ApplicationServices;
if (sp.GetService(typeof(MyJob)) == null)
    throw new InvalidOperationException("MyJob is not registered in DI.");

Prevention

When it happens

Trigger: A non-static job method runs; scope.Resolve(job.Type) returns null. This happens when the JobActivator (e.g. AspNetCoreJobActivator, a DI-based activator) has no registration for the job's type.

Common situations: Forgetting to register the job class in the DI container when using scoped activators. Registering the implementation but resolving by a different type. A type that the activator's scope doesn't know about (e.g. registered in a different scope or assembly).

Related errors


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