abpframework/abp · error · ArgumentException

At least one of 'Period' or 'CronExpression' must be set.

Error message

At least one of 'Period' or 'CronExpression' must be set.

What it means

Thrown by DynamicBackgroundWorkerSchedule.Validate when neither Period nor CronExpression is set (Period is null and CronExpression is null/whitespace). A dynamic worker must have at least one scheduling directive; with neither, the manager has no way to determine when to run the worker. Validate is called automatically by AddAsync and UpdateScheduleAsync.

Source

Thrown at framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/DynamicBackgroundWorkerSchedule.cs:24

{
    public const int DefaultPeriod = 60000;

    public int? Period { get; set; }

    public string? CronExpression { get; set; }

    public virtual void Validate()
    {
        if (Period.HasValue && Period.Value <= 0)
        {
            throw new ArgumentException(
                $"Period must be greater than 0 when provided. Given value: {Period.Value}.",
                nameof(Period));
        }

        if (Period == null && string.IsNullOrWhiteSpace(CronExpression))
        {
            throw new ArgumentException(
                "At least one of 'Period' or 'CronExpression' must be set.");
        }
    }
}

View on GitHub (pinned to 7ed43b1931)

Solutions

  1. Set Period to a positive millisecond value (e.g. 60000) on the schedule.
  2. Set CronExpression to a valid cron string (requires Hangfire/Quartz provider; the default in-memory manager rejects cron).
  3. Read at least one scheduling value from configuration and ensure it is non-null before constructing the schedule.

Example fix

// before — schedule has neither field set
await manager.AddAsync("worker",
    new DynamicBackgroundWorkerSchedule(), handler); // throws

// after — set a period
await manager.AddAsync("worker",
    new DynamicBackgroundWorkerSchedule { Period = 60000 }, handler);
Defensive patterns

Strategy: validation

Validate before calling

var schedule = new DynamicBackgroundWorkerSchedule();
if (configuredPeriod.HasValue) schedule.Period = configuredPeriod;
else if (!string.IsNullOrWhiteSpace(configuredCron)) schedule.CronExpression = configuredCron;
else throw new InvalidOperationException("Configure either WorkerPeriod or WorkerCron in settings.");
schedule.Validate();

Type guard

static bool HasAtLeastOneSchedule(DynamicBackgroundWorkerSchedule s) => s.Period.HasValue || !string.IsNullOrWhiteSpace(s.CronExpression);

Prevention

When it happens

Trigger: Constructing a DynamicBackgroundWorkerSchedule with default values (Period = null, CronExpression = null) and passing it to IDynamicBackgroundWorkerManager.AddAsync or UpdateScheduleAsync. Also thrown on a manual Validate() call on an unconfigured schedule.

Common situations: Building a schedule from optional configuration fields where both Period and CronExpression keys are absent. Intending to set Period but the property name was misspelled or the assignment was lost in a refactor. Passing a schedule object that was constructed but never populated.

Related errors


AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13). Data as JSON: /api/errors/848a37cc40aaff38. Report an issue: GitHub.