tinyhumansai/openhuman · error
Invalid schedule: every_ms must be > 0
Error message
Invalid schedule: every_ms must be > 0
What it means
In next_run_for_schedule, Schedule::Every with every_ms == 0 is rejected: a zero interval would mean 'run continuously' and spin the scheduler. validate_schedule carries an identical guard (schedule.rs:83) so the same condition also fails at validation time.
Source
Thrown at src/openhuman/cron/schedule.rs:50
next_utc,
active.start,
active.end
);
current_from = next_utc;
} else {
return Ok(next_utc);
}
}
tracing::warn!(
"[cron] no occurrence found within active_hours for expr={} after 100,000 candidates",
expr
);
anyhow::bail!("No future occurrence found within active hours after 100,000 attempts")
}
Schedule::At { at } => Ok(*at),
Schedule::Every { every_ms } => {
if *every_ms == 0 {
anyhow::bail!("Invalid schedule: every_ms must be > 0");
}
let ms = i64::try_from(*every_ms).context("every_ms is too large")?;
let delta = ChronoDuration::milliseconds(ms);
from.checked_add_signed(delta)
.ok_or_else(|| anyhow::anyhow!("every_ms overflowed DateTime"))
}
}
}
pub fn validate_schedule(schedule: &Schedule, now: DateTime<Utc>) -> Result<()> {
match schedule {
Schedule::Cron {
expr,
tz,
active_hours,
} => {
let _ = normalize_expression(expr)?;
if let Some(active) = active_hours {View on GitHub (pinned to 7491200858)
Solutions
- Set a positive interval (every_ms > 0), sized to a sane floor (e.g. >= 1000ms) for scheduler load
- Clamp user-supplied frequencies at the boundary: every_ms = max(input, MIN_INTERVAL)
- If 'run immediately' was intended, that is not an interval — use a one-shot Schedule::At or trigger the job manually
Example fix
// before
Schedule::Every { every_ms: 0 }
// after
Schedule::Every { every_ms: 60_000 } Defensive patterns
Strategy: validation
Validate before calling
if let Schedule::Every { every_ms } = &schedule {
const MIN_INTERVAL_MS: u64 = 1_000;
assert!(*every_ms >= MIN_INTERVAL_MS, "interval is zero / too small");
} Type guard
function isValidEverySchedule(s: Schedule): boolean {
return s.type !== 'every' || (s.every_ms ?? 0) > 0;
} Prevention
- Clamp interval inputs to a documented minimum at the UI boundary
- Default frequency fields to a real value, never 0
- Unit-test schedule constructors with boundary values (0, 1, u64 max)
When it happens
Trigger: Constructing an every-interval job with every_ms: 0 — UI frequency inputs defaulting to 0, division that computes 0, hand-written JSON, or deserialized legacy data where the field was never set — and then asking for its next run.
Common situations: Derived intervals (total/count landing on 0); 'run every N items' style inputs with N unset; test fixtures probing edge values.
Related errors
- No future occurrence found within active hours after 100,000
- At least one of --expression, --tz, --command, or --name mus
- Cannot update expression/tz on a non-cron schedule
- Invalid schedule: 'at' must be in the future
- Invalid cron expression: {expression} (expected 5, 6, or 7 f
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/36c16053c5de3b28.
Report an issue: GitHub.