abpframework/abp · error · AbpException
Cannot convert period: {period} to cron expression, use Hang
Error message
Cannot convert period: {period} to cron expression, use HangfireBackgroundWorkerBase to define worker What it means
Thrown by HangfireBackgroundWorkerManager.GetCron when converting a worker's Period (in milliseconds) to a cron expression and the period exceeds 31 days. The converter only supports ranges expressible in standard cron: seconds (<=59s), minutes, hours, and days up to 31. Periods longer than a month cannot be represented because cron has no 'every N months' field in this conversion logic.
Source
Thrown at framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs:185
}
else if (time.TotalMinutes <= 59)
{
var minutes = Math.Max(1, (int)Math.Round(time.TotalMinutes));
cron = $"*/{minutes} * * * *";
}
else if (time.TotalHours <= 23)
{
var hours = Math.Max(1, (int)Math.Round(time.TotalHours));
cron = $"0 */{hours} * * *";
}
else if(time.TotalDays <= 31)
{
var days = Math.Max(1, (int)Math.Round(time.TotalDays));
cron = $"0 0 0 1/{days} * *";
}
else
{
throw new AbpException($"Cannot convert period: {period} to cron expression, use HangfireBackgroundWorkerBase to define worker");
}
return cron;
}
}
View on GitHub (pinned to 7ed43b1931)
Solutions
- Reduce the Period to 31 days or less (<= 2,678,400,000 ms).
- For periods longer than a month, subclass HangfireBackgroundWorkerBase and set an explicit cron expression directly instead of relying on Period-to-cron conversion.
- If the large period was a unit mistake, correct the Period to the intended interval.
Example fix
// before — period exceeds 31 days
public class MonthlyReportWorker : AsyncPeriodicBackgroundWorkerBase
{
public MonthlyReportWorker()
{
Period = (int)TimeSpan.FromDays(45).TotalMilliseconds; // throws
}
}
// after — use HangfireBackgroundWorkerBase with explicit cron
public class MonthlyReportWorker : HangfireBackgroundWorkerBase
{
public MonthlyReportWorker()
{
CronExpression = "0 0 1 * *"; // 1st of every month
}
} Defensive patterns
Strategy: validation
Validate before calling
int maxPeriodMs = (int)TimeSpan.FromDays(31).TotalMilliseconds;
if (worker.Period > maxPeriodMs)
{
throw new InvalidOperationException($"Period {worker.Period} ms exceeds the 31-day cron limit. Use HangfireBackgroundWorkerBase with an explicit CronExpression.");
} Type guard
static bool IsCronConvertiblePeriod(int periodMs) => TimeSpan.FromMilliseconds(periodMs).TotalDays <= 31;
Prevention
- Keep PeriodicBackgroundWorkerBase periods at or below 31 days when using Hangfire.
- For monthly+ intervals, subclass HangfireBackgroundWorkerBase and set CronExpression directly.
- Centralize worker period constants and validate them against the 31-day ceiling at startup.
When it happens
Trigger: Setting an AsyncPeriodicBackgroundWorkerBase or PeriodicBackgroundWorkerBase Period to a value greater than 31 days (2,678,400,000 ms) while using the Hangfire background workers provider. The converter is invoked automatically when the worker is registered with HangfireBackgroundWorkerManager.
Common situations: Configuring a monthly or quarterly maintenance worker with Period = TimeSpan.FromDays(60). Setting a Period meant as seconds but accidentally as milliseconds, resulting in an enormous value (e.g. 60,000,000 ms ≈ 16 hours is fine, but 6,000,000,000 exceeds the limit).
Related errors
- Cannot convert period: {period} to cron expression.
- Cannot convert period: {period} to cron expression.
- Both 'Period' and 'CronExpression' are not set for {worker.G
- The default in-memory background worker manager does not sup
- Period must be greater than 0 when provided. Given value: {P
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/9a197266df30e3b4.
Report an issue: GitHub.