abpframework/abp · error · AbpException

Cannot convert period: {period} to cron expression.

Error message

Cannot convert period: {period} to cron expression.

What it means

Thrown by AbpTickerQBackgroundWorkerManager.GetCron when converting a worker's Period (milliseconds) to a cron expression and the period exceeds 31 days. The TickerQ cron converter covers sub-minute up to monthly intervals; periods longer than 31 days have no cron representation in this logic.

Source

Thrown at framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQBackgroundWorkerManager.cs:103

            var minutes = (int)Math.Round(time.TotalMinutes);
            return $"*/{minutes} * * * *";
        }

        if (time.TotalHours < 24)
        {
            // Run every N hours
            var hours = (int)Math.Round(time.TotalHours);
            return $"0 */{hours} * * *";
        }

        if (time.TotalDays <= 31)
        {
            // Run every N days
            var days = (int)Math.Round(time.TotalDays);
            return $"0 0 */{days} * *";
        }

        throw new AbpException($"Cannot convert period: {period} to cron expression.");
    }
}

View on GitHub (pinned to 7ed43b1931)

Solutions

  1. Reduce the Period to 31 days or fewer.
  2. Set a CronExpression on the worker for intervals longer than a month (e.g. "0 0 1 1 *" for January 1st each year).
  3. Correct any millisecond/second unit mismatch in the Period value.

Example fix

// before
public class YearlyAuditWorker : AsyncPeriodicBackgroundWorkerBase
{
    public YearlyAuditWorker()
    {
        Period = (int)TimeSpan.FromDays(365).TotalMilliseconds; // throws
    }
}

// after — use a cron expression
public class YearlyAuditWorker : AsyncPeriodicBackgroundWorkerBase
{
    public YearlyAuditWorker()
    {
        CronExpression = "0 0 1 1 *";
    }
}
Defensive patterns

Strategy: validation

Validate before calling

if (worker.Period.HasValue && TimeSpan.FromMilliseconds(worker.Period.Value).TotalDays > 31)
{
    throw new InvalidOperationException("Period exceeds 31 days for TickerQ; set CronExpression instead.");
}

Type guard

static bool IsCronConvertiblePeriod(int periodMs) => TimeSpan.FromMilliseconds(periodMs).TotalDays <= 31;

Prevention

When it happens

Trigger: Registering a periodic worker under the TickerQ provider with Period set to more than 31 days (2,678,400,000 ms) and no CronExpression. The AddAsync flow calls GetCron(period) because cronExpression was null.

Common situations: A long-interval maintenance worker (quarterly/yearly) registered with a Period value. A unit confusion where a value meant as seconds was supplied as milliseconds, exceeding the ceiling.

Related errors


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