HangfireIO/Hangfire · error · InvalidOperationException
JobActivator returned NULL instance of the
Error message
JobActivator returned NULL instance of the '{Type}' type. What it means
Thrown as InvalidOperationException (wrapped in JobPerformanceException) when a JobActivator.ActivateJob returns null for the job's Type. Hangfire requires a non-null instance to invoke the method; a null return usually signals a misconfigured DI scope (e.g. a service not registered, a scoped service resolved outside its scope, or a manual activator returning null). The obsolete Activate() private method checks the result at line 84.
Solutions
- Register the job type in your DI container so the activator can resolve it (e.g. services.AddTransient<MyJob>()).
- Verify the job class has a public parameterless constructor if using the default JobActivator (Activator.CreateInstance), or register it for DI.
- If using a custom JobActivator, make ActivateJob throw a descriptive exception instead of returning null.
- Ensure the job type still exists in the deployed assembly — stale jobs referencing removed types should be deleted from storage.
Example fix
// before — MyJob not registered, DI activator returns null // job fails: JobActivator returned NULL instance of the 'MyJob' type. // after services.AddTransient<MyJob>(); services.AddHangfire((sp, cfg) => cfg.UseActivator(new AspNetCoreJobActivator(sp)));
Defensive patterns
Strategy: try-catch
Validate before calling
// Before perform, verify the type is resolvable by your activator:
// (DI containers expose IsRegistered / TryResolve)
if (!serviceProvider.GetService(typeof(MyJob)).TryGetTarget(out _))
throw new InvalidOperationException("Job type not registered."); Try / catch
try { job.Perform(activator, token); }
catch (JobPerformanceException ex) when (ex.InnerException is InvalidOperationException ioe
&& ioe.Message.Contains("returned NULL"))
{
logger.LogError(ex, "Job type could not be activated — register it in DI.");
} Prevention
- Register every job type in your DI container.
- Implement a custom JobActivator that throws a descriptive error instead of returning null.
- Use AspNetCoreJobActivator (or equivalent) scoped correctly to resolve job types.
When it happens
Trigger: Job.Perform (obsolete) invokes Activate(activator) -> activator.ActivateJob(Type) which returns null. Common with a custom JobActivator whose Resolve/ActivateJob returns null, or a DI-based activator (AspNetCoreJobActivator, Autofac) that cannot resolve the job type because it isn't registered in the container.
Common situations: The job class is not registered in the DI container (especially with scoped/lifetime resolution in ASP.NET Core); a constructor on the job type throws silently or the DI provider returns null for an unregistered service; using a third-party activator that returns null for open generics or interface-based jobs; a stale job in storage referencing a type that was since removed from the assembly.
Related errors
- An exception occurred during job activation.
- activator
- An exception occurred during arguments deserialization.
- Job has been performed, but an exception occurred during…
- activator
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/e98469fd774f95fd.
Report an issue: GitHub.
Appendix: source
Thrown at src/Hangfire.Core/Obsolete/Job.Obsolete.cs:84
}
finally
{
Dispose(instance);
}
return result;
}
[Obsolete("Will be removed in 2.0.0")]
private object Activate(JobActivator activator)
{
try
{
var instance = activator.ActivateJob(Type);
if (instance == null)
{
throw new InvalidOperationException($"JobActivator returned NULL instance of the '{Type}' type.");
}
return instance;
}
catch (Exception ex) when (ex.IsCatchableExceptionType())
{
throw new JobPerformanceException(
"An exception occurred during job activation.",
ex);
}
}
[Obsolete("Will be removed in 2.0.0")]
private object[] GetArguments(IJobCancellationToken cancellationToken)
{
try
{
var parameters = Method.GetParameters();View on GitHub (pinned to c236dd0f93)