HangfireIO/Hangfire · error · InvalidOperationException
Can't perform a background job with a null job.
Error message
Can't perform a background job with a null job.
What it means
Thrown by CoreBackgroundJobPerformer.Perform when the BackgroundJob.Job property is null at execution time. The performer needs a Job to know which method to invoke; a null Job means the background-job record in storage is incomplete or corrupt (no method/type serialized).
Source
Thrown at src/Hangfire.Core/Server/CoreBackgroundJobPerformer.cs:55
private readonly JobActivator _activator;
private readonly TaskScheduler _taskScheduler;
public CoreBackgroundJobPerformer([NotNull] JobActivator activator, [CanBeNull] TaskScheduler taskScheduler)
{
_activator = activator ?? throw new ArgumentNullException(nameof(activator));
_taskScheduler = taskScheduler;
}
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;
}View on GitHub (pinned to c236dd0f93)
Solutions
- Let the job fail and be moved to the Failed state; then delete it from storage to stop retries.
- Investigate how the job was enqueued — ensure BackgroundJob.Enqueue/Job.FromExpression is used so the Job is serialized.
- If using a custom storage, verify it round-trips the InvocationData/Job payload correctly.
Example fix
// before — custom enqueuer omitted the method payload
// (job stored without serialized Job)
// after — enqueue through the standard client so Job is serialized
BackgroundJob.Enqueue(() => Console.WriteLine("ok")); Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure jobs are always enqueued with a real method expression so Job is non-null if (job == null) throw new ArgumentNullException(nameof(job)); BackgroundJob.Enqueue(() => job.Run());
Try / catch
// Let the performer throw; the job moves to Failed state, then purge it // (no user-side try/catch — handle via dashboard or retry policy)
Prevention
- Always enqueue via BackgroundJob.Enqueue(() => ...) or IBackgroundJobClient so the Job is serialized.
- Avoid creating background-job records manually in storage.
- Monitor the failed-jobs list and delete corrupt entries promptly.
When it happens
Trigger: A worker dequeues a background job whose serialized InvocationData did not yield a Job, or the BackgroundJob object was constructed without a Job. This is reached during actual job performance on the server.
Common situations: Corrupt job record in storage (missing Job fields). A custom enqueuer that created a background job without a proper method expression. Storage migration that lost payload. Race condition where a job was deleted but still being processed.
Related errors
- Could not get a value of the job parameter `{name}`. See inn
- The 'Job' field has a null or empty value
- No dispatchers registered for the processing server.
- JobActivator returned NULL instance of the '{context.Backgro
- An exception occurred during performance of the job.
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/04ffa79f61150829.
Report an issue: GitHub.