HangfireIO/Hangfire · error · ArgumentNullException
cronExpression
Error message
cronExpression
What it means
Thrown by the obsolete RecurringJob.AddOrUpdate(Expression<Action>, Func<string> cronExpression, ...) overload when the cronExpression factory delegate is null. Hangfire accepts a Func<string> so the cron expression can be evaluated lazily. A null factory means there is no way to obtain the schedule.
Source
Thrown at src/Hangfire.Core/RecurringJob.cs:58
}
}
set
{
lock (ManagerFactoryLock)
{
_managerFactory = value;
}
}
}
[Obsolete("Please use an overload with the explicit recurringJobId parameter and RecurringJobOptions instead. Will be removed in 2.0.0.")]
public static void AddOrUpdate(
[NotNull, InstantHandle] Expression<Action> methodCall,
[NotNull] Func<string> cronExpression,
[CanBeNull] TimeZoneInfo timeZone = null,
[NotNull] string queue = EnqueuedState.DefaultQueue)
{
if (cronExpression == null) throw new ArgumentNullException(nameof(cronExpression));
AddOrUpdate(methodCall, cronExpression(), timeZone, queue);
}
[Obsolete("Please use an overload with the explicit recurringJobId parameter instead. Will be removed in 2.0.0.")]
public static void AddOrUpdate(
[NotNull, InstantHandle] Expression<Action> methodCall,
[NotNull] Func<string> cronExpression,
[NotNull] RecurringJobOptions options)
{
if (cronExpression == null) throw new ArgumentNullException(nameof(cronExpression));
AddOrUpdate(methodCall, cronExpression(), options);
}
[Obsolete("Please use an overload with the explicit recurringJobId parameter and RecurringJobOptions instead. Will be removed in 2.0.0.")]
public static void AddOrUpdate<T>(
[NotNull, InstantHandle] Expression<Action<T>> methodCall,
[NotNull] Func<string> cronExpression,
[CanBeNull] TimeZoneInfo timeZone = null,View on GitHub (pinned to c236dd0f93)
Solutions
- Provide a non-null Func<string> that returns the cron expression, e.g. () => Cron.Daily().
- Migrate to the non-obsolete overload that takes an explicit recurringJobId and a string cronExpression with RecurringJobOptions.
- If the cron source may be absent, validate it before calling AddOrUpdate and skip or log instead of passing null.
Example fix
// before
RecurringJob.AddOrUpdate(() => Job.Run(), cronExpression: null);
// after
RecurringJob.AddOrUpdate("my-job", () => Job.Run(), Cron.Daily()); Defensive patterns
Strategy: validation
Validate before calling
Func<string> cronFactory = () => _config["Cron"];
if (cronFactory == null) throw new InvalidOperationException("Cron factory is not configured.");
RecurringJob.AddOrUpdate(() => Work(), cronFactory, TimeZoneInfo.Utc); Prevention
- Migrate away from the obsolete AddOrUpdate overload to the explicit-id string-cron version.
- Resolve cron from config and validate it is non-null at startup.
- Use Cron helper methods (Cron.Daily()) as the factory return to avoid null.
When it happens
Trigger: Calling RecurringJob.AddOrUpdate(() => MyMethod(), cronExpression: null) or passing a variable that is null for the Func<string> cronExpression parameter of this specific obsolete overload.
Common situations: Migrating from the obsolete overload and forgetting to supply the cron factory. Storing cron in configuration that resolves to null. Using a helper that conditionally returns null from a cron-selection function.
Related errors
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/47b32d3cdebb387e.
Report an issue: GitHub.