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

  1. Provide a non-null Func<string> that returns the cron expression, e.g. () => Cron.Daily().
  2. Migrate to the non-obsolete overload that takes an explicit recurringJobId and a string cronExpression with RecurringJobOptions.
  3. 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

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.