HKUDS/Vibe-Trading · error · ValueError
cron field {part!r} is out of range; expected {low}-{high}
Error message
cron field {part!r} is out of range; expected {low}-{high} What it means
_validate_cron_field validates one field of a 5-field cron expression against its allowed numeric range. For step syntax (*/n), the step value n itself must fall within the field's range; a step like */61 for minutes is rejected because it is out of range for the field.
Source
Thrown at agent/src/scheduled_research/models.py:52
_CRON_STEP_RE = re.compile(r"^\*/[1-9][0-9]*$")
_CRON_ATOM_RE = re.compile(r"^([0-9]+)(?:-([0-9]+))?$")
_CRON_PARTS = 5
# Inclusive (low, high) bounds per cron field: minute hour day-of-month month
# day-of-week. Every number in a field — a bare value, a ``*/n`` step, or
# either end of a range — is validated against these bounds so out-of-range
# values (e.g. minute ``99``) are rejected. Day-of-week uses the cron
# convention Sunday == 0; ``7`` is not accepted as a Sunday alias.
CRON_BOUNDS = ((0, 59), (0, 23), (1, 31), (1, 12), (0, 6))
def _validate_cron_field(part: str, low: int, high: int) -> None:
"""Raise ``ValueError`` when one cron field is malformed or out of range."""
if part == "*":
return
if _CRON_STEP_RE.fullmatch(part):
value = int(part[2:])
if not low <= value <= high:
raise ValueError(f"cron field {part!r} is out of range; expected {low}-{high}")
return
for atom in part.split(","):
match = _CRON_ATOM_RE.fullmatch(atom)
if match is None:
raise ValueError(
f"cron field {part!r} is not valid; each field must be *, */n, "
f"or a comma-separated list of numbers and low-high ranges"
)
start = int(match.group(1))
end = int(match.group(2)) if match.group(2) is not None else start
if start > end:
raise ValueError(f"cron range {atom!r} is reversed; expected low-high")
if start < low or end > high:
raise ValueError(f"cron field {atom!r} is out of range; expected {low}-{high}")
def parse_cron_field(part: str, low: int, high: int) -> Optional[Set[int]]:
"""Expand one validated cron field into its matching values.View on GitHub (pinned to 80ffdda44c)
Solutions
- Keep step values within the field's range: minutes 0-59, hours 0-23, day-of-month 1-31, month 1-12, day-of-week 0-6.
- For intervals exceeding the field (e.g. every 90 minutes), use the millisecond-interval schedule form or a range list ('0,30 0,1,2... * * *' style).
- Validate schedule strings with validate_schedule before persisting jobs.
Example fix
# before
validate_schedule('*/90 * * * *')
# after
validate_schedule('9000000') # every 90 minutes as ms interval Defensive patterns
Strategy: validation
Validate before calling
from scheduled_research.models import validate_schedule
validate_schedule(f'{minute_step_in_0_59} * * * *') if 0 < step <= 59 else validate_schedule(str(step * 60_000)) Try / catch
try:
validate_schedule(schedule)
except ValueError as e:
return bad_request(f'invalid schedule: {e}') Prevention
- Keep step values within field bounds; use ms-intervals for large steps.
- Validate at ingestion, not at execution time.
When it happens
Trigger: validate_schedule('*/61 * * * *') (minute step 61 > 59), '0 */25 * * *' (hour step 25 > 23), or a programmatically generated step value exceeding the field's maximum.
Common situations: Building schedules from user input or templates where a computed interval (e.g. 'every 90 minutes' -> */90) ignores cron's per-field bounds; copying Vixie-cron syntax that this simplified parser treats differently.
Related errors
- cron field {part!r} is not valid; each field must be *, */n,
- cron range {atom!r} is reversed; expected low-high
- cron field {atom!r} is out of range; expected {low}-{high}
- schedule must be a non-empty string
- interval is too large; expected at most 15 digits of millise
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/7da3643ab4ea7a97.
Report an issue: GitHub.