HangfireIO/Hangfire · error · InvalidOperationException
The 'Job' field has a null or empty value
Error message
The 'Job' field has a null or empty value
What it means
Thrown by TriggerRecurringJob when the RecurringJobEntity.Job payload is null, meaning the recurring job entry in storage has no serialized job definition. Hangfire cannot create a background job without a target method, so triggering is impossible. This usually means the storage entry is incomplete or corrupt.
Source
Thrown at src/Hangfire.Core/RecurringJobExtensions.cs:112
}
public static BackgroundJob TriggerRecurringJob(
[NotNull] this IBackgroundJobFactory factory,
[NotNull] JobStorage storage,
[NotNull] IStorageConnection connection,
[NotNull] IProfiler profiler,
[NotNull] RecurringJobEntity recurringJob,
DateTime now)
{
if (factory == null) throw new ArgumentNullException(nameof(factory));
if (storage == null) throw new ArgumentNullException(nameof(storage));
if (connection == null) throw new ArgumentNullException(nameof(connection));
if (profiler == null) throw new ArgumentNullException(nameof(profiler));
if (recurringJob == null) throw new ArgumentNullException(nameof(recurringJob));
if (recurringJob.Job == null)
{
throw new InvalidOperationException("The 'Job' field has a null or empty value");
}
var job = InvocationData.DeserializePayload(recurringJob.Job).DeserializeJob();
var context = new CreateContext(storage, connection, job, null, null, profiler, null);
context.Parameters["RecurringJobId"] = recurringJob.RecurringJobId;
context.Parameters["Time"] = JobHelper.ToTimestamp(now);
var backgroundJob = factory.Create(context);
recurringJob.LastExecution = now;
recurringJob.LastJobId = backgroundJob?.Id;
return backgroundJob;
}
public static void EnqueueBackgroundJob(
[NotNull] this IStateMachine stateMachine,View on GitHub (pinned to c236dd0f93)
Solutions
- Recreate the recurring job with RecurringJob.AddOrUpdate to restore the serialized Job payload.
- Remove the orphaned entry from the 'recurring-jobs' set if it is no longer needed (RecurringJob.RemoveIfExists).
- If using a custom storage, verify that AddOrUpdate persists the Job field atomically alongside the set membership.
Example fix
// before — triggering a corrupt entry
RecurringJob.Trigger("broken-job"); // throws
// after — recreate then trigger
RecurringJob.AddOrUpdate("broken-job", () => Work(), Cron.Daily());
RecurringJob.Trigger("broken-job"); Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the recurring job has a Job payload before triggering
var job = connection.GetRecurringJobs().FirstOrDefault(j => j.Id == id);
if (job?.Job == null) { /* recreate or skip */ } Try / catch
try { RecurringJob.Trigger(id); }
catch (InvalidOperationException ex) when (ex.Message.Contains("'Job' field"))
{
RecurringJob.AddOrUpdate(id, () => Work(), cron);
} Prevention
- Always create recurring jobs through RecurringJob.AddOrUpdate so the Job payload is serialized.
- Avoid manual storage edits to recurring-job entries.
- Use custom storages that write the Job field atomically with set membership.
When it happens
Trigger: Calling RecurringJob.Trigger(id) or the scheduler processing a recurring job whose 'Job' hash field is missing or empty. Also reachable through IBackgroundJobFactory.TriggerRecurringJob directly.
Common situations: A recurring job was partially written to storage (interrupted write, custom storage bug). Manual deletion of the Job field. A migration or storage switch that dropped the payload. Triggering a job that was never fully created via AddOrUpdate.
Related errors
- Misfire option '{0}' is not supported.
- Can't perform a background job with a null job.
- Could not get a value of the job parameter `{name}`. See inn
- Current JobStorage instance has not been initialized yet. Yo
- cronExpression
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/170d3856e5338bcc.
Report an issue: GitHub.