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
- Reduce the Period to 31 days or fewer.
- Set a CronExpression on the worker for intervals longer than a month (e.g. "0 0 1 1 *" for January 1st each year).
- 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
- Keep TickerQ worker periods at or below 31 days.
- For longer intervals, set CronExpression on the worker.
- Validate periods centrally during module configuration.
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
- Cannot convert period: {period} to cron expression, use Hang
- Cannot convert period: {period} to cron expression.
- Both 'Period' and 'CronExpression' are not set for {worker.G
- Could not find 'DoWorkAsync' method on type '{workerType.Ful
- Could not find 'DoWork' method on type '{workerType.FullName
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/3feec550fa8e058f.
Report an issue: GitHub.