affaan-m/ECC · error · anyhow::Error

invalid cron expression `{trimmed}`: expected 5, 6, or 7 fie

Error message

invalid cron expression `{trimmed}`: expected 5, 6, or 7 fields but found {fields}

What it means

The parse_cron_schedule function normalizes cron expressions before passing them to CronSchedule::from_str. It expects exactly 5, 6, or 7 whitespace-separated fields. Five-field expressions (traditional Unix cron) get a '0 ' prefix for seconds. Anything else is rejected as malformed.

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 01e15490f0)

Solutions

  1. Ensure the cron expression has exactly 5 fields (min hour day month weekday), 6 (with seconds), or 7 (with seconds and years)
  2. Trim and validate the expression's field count before scheduling
  3. Check for accidental double-spaces or tabs that split_whitespace would count as extra fields
  4. Use a cron expression validator or linter in config tooling

Example fix

// before
let schedule = parse_cron_schedule("0 9 * *")?;

// after
let schedule = parse_cron_schedule("0 9 * * *")?;  // 5 fields: min hour day month weekday
Defensive patterns

Strategy: validation

Validate before calling

fn validate_cron_fields(expr: &str) -> Result<()> {
    let count = expr.trim().split_whitespace().count();
    match count {
        5 | 6 | 7 => Ok(()),
        n => Err(anyhow!("cron expression must have 5, 6, or 7 fields, found {n}")),
    }
}

Type guard

fn is_valid_cron_field_count(expr: &str) -> bool {
    matches!(expr.trim().split_whitespace().count(), 5 | 6 | 7)
}

Prevention

When it happens

Trigger: Passing a cron expression to parse_cron_schedule or next_schedule_run_at that does not have exactly 5, 6, or 7 whitespace-separated fields.

Common situations: Typo in schedule config (e.g., extra spaces counted as fields, missing field). Using a non-standard cron dialect. Copy-paste error from documentation that uses dashes instead of spaces. Empty schedule string.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/33bd0387c52d7a96. Report an issue: GitHub.