affaan-m/ECC · error · anyhow::Error
invalid cron expression
Error message
invalid cron expression `{trimmed}`: expected 5, 6, or 7 fields but found {fields} What it means
parse_cron_schedule validates cron expressions by counting whitespace-separated fields. Standard cron has 5 fields; this parser accepts 5 (prepends a seconds field), 6, or 7. Any other field count is rejected with this message before CronSchedule::from_str is attempted, giving a clearer diagnostic.
Solutions
- Provide a valid 5-field cron expression, e.g. '0 9 * * *' for daily at 9am
- Count the fields: minute hour day-of-month month day-of-week (a 6th seconds field or 7th year field is allowed)
- Replace @daily/@hourly descriptors with equivalent explicit cron expressions
- Trim stray whitespace and avoid natural-language schedule strings
Example fix
// before
parse_cron_schedule("every day at 9")?;
// after
parse_cron_schedule("0 9 * * *")?; // 5 fields: daily at 09:00 Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_cron(expr: &str) -> bool {
let n = expr.trim().split_whitespace().count();
(5..=7).contains(&n) && !expr.trim().starts_with('@')
} Try / catch
match parse_cron_schedule(input) {
Err(e) if e.to_string().contains("expected 5, 6, or 7 fields") => {
eprintln!("'{input}' is not valid cron; use 5 space-separated fields like '0 9 * * *'");
Err(e)
}
other => other,
} Prevention
- Validate cron input in the UI with a field counter before submission
- Disallow natural-language and @descriptor schedules
- Use a cron-construction widget rather than free-text entry
When it happens
Trigger: Calling schedule creation (which calls parse_cron_schedule) with a string like 'every day' (0 fields), '* * *' (3 fields), or a miscounted expression whose whitespace-separated token count is not 5, 6, or 7.
Common situations: Users pasting natural language ('every morning') instead of cron syntax; forgetting a field ('* * *' instead of '* * * * *'); using descriptors like '@daily' or '@hourly' that split to one token; extra spaces causing miscounts or copy/paste errors.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- effect recipe needs at least three scheduled events
- invalid cron expression
- invalid discussion id
- Invalid format: . Use text or json.
- invalid repository
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/33bd0387c52d7a96.
Report an issue: GitHub.
Appendix: source
Thrown at ecc2/src/session/manager.rs:2365
}
fn resolve_session(db: &StateStore, id: &str) -> Result<Session> {
let session = if id == "latest" {
db.get_latest_session()?
} else {
db.get_session(id)?
};
session.ok_or_else(|| anyhow::anyhow!("Session not found: {id}"))
}
fn parse_cron_schedule(expr: &str) -> Result<CronSchedule> {
let trimmed = expr.trim();
let normalized = match trimmed.split_whitespace().count() {
5 => format!("0 {trimmed}"),
6 | 7 => trimmed.to_string(),
fields => {
anyhow::bail!(
"invalid cron expression `{trimmed}`: expected 5, 6, or 7 fields but found {fields}"
)
}
};
CronSchedule::from_str(&normalized)
.with_context(|| format!("invalid cron expression `{trimmed}`"))
}
fn next_schedule_run_at(
expr: &str,
after: chrono::DateTime<chrono::Utc>,
) -> Result<chrono::DateTime<chrono::Utc>> {
parse_cron_schedule(expr)?
.after(&after)
.next()
.map(|value| value.with_timezone(&chrono::Utc))
.ok_or_else(|| anyhow::anyhow!("cron expression `{expr}` did not yield a future run time"))
}View on GitHub (pinned to 8321021c54)