Hmbown/CodeWhale · error · anyhow::Error
CRON {field_name} step must be >= 1
Error message
CRON {field_name} step must be >= 1 What it means
A step value of 0 in a cron field ('base/step') is rejected; steps must parse as u32 and be >= 1. '*/0', '5-10/0', and name-based bases with '/0' all fail here. A non-numeric step produces the sibling 'Failed to parse CRON {field} step' error instead.
Source
Thrown at crates/tui/src/automation_manager.rs:738
fn parse(raw: &str, min: u32, max: u32, names: CronNameMap, field_name: &str) -> Result<Self> {
let trimmed = raw.trim();
if trimmed.is_empty() {
bail!("CRON {field_name} field must not be empty");
}
let mut values = Vec::new();
let is_wildcard = trimmed == "*";
for part in trimmed.split(',') {
let part = part.trim();
if part.is_empty() {
bail!("CRON {field_name} field contains an empty list item");
}
let (base, step) = if let Some((base, step)) = part.split_once('/') {
let step = step
.trim()
.parse::<u32>()
.with_context(|| format!("Failed to parse CRON {field_name} step"))?;
if step == 0 {
bail!("CRON {field_name} step must be >= 1");
}
(base.trim(), step)
} else {
(part, 1)
};
let range = if base == "*" {
(min, max)
} else if let Some((start, end)) = base.split_once('-') {
let start = parse_cron_atom(start.trim(), min, max, names, field_name)?;
let end = parse_cron_atom(end.trim(), min, max, names, field_name)?;
if start > end {
bail!("CRON {field_name} range start must be <= end");
}
(start, end)
} else {
let start = parse_cron_atom(base, min, max, names, field_name)?;
if part.contains('/') {View on GitHub (pinned to 0c42157ee5)
Solutions
- Use a step >= 1: */5, */15, 2-30/10
- Guard computed steps against 0 before formatting the EXPR
- For 'as often as possible' use plain '*' (implicit step 1)
- Dry-run parse_rrule on the final expression
Example fix
// before rrule = "FREQ=CRON;EXPR=*/0 * * * *" // after rrule = "FREQ=CRON;EXPR=*/5 * * * *"
Defensive patterns
Strategy: validation
Validate before calling
fn cron_steps_positive(expr: &str) -> bool {
expr.split_whitespace().all(|field| {
field.split(',').all(|item| match item.split_once('/') {
Some((_, step)) => step.trim().parse::<u32>().is_ok_and(|s| s >= 1),
None => true,
})
})
} Prevention
- Clamp generated steps to at least 1
- Treat step 0 as invalid at the UI layer before submission
- Remember a missing step defaults to 1
- Dry-run the EXPR via parse_rrule
When it happens
Trigger: EXPR='*/0 * * * *' (every zero minutes); EXPR='0 0 */0 * *'; templated steps where a computed divisor evaluated to 0.
Common situations: Templated cron generators computing a step from user-supplied numbers; placeholder '*/N' strings with N never substituted.
Related errors
- Unsupported RRULE field '{key}' for CRON. Allowed: FREQ,EXPR
- CRON EXPR must have exactly 5 fields: minute hour day-of-mon
- CRON EXPR day-of-month/month combination can never occur
- CRON {field_name} field must not be empty
- CRON {field_name} field contains an empty list item
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/e47b883b37902759.
Report an issue: GitHub.