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

  1. 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.
  2. 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).
  3. 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

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


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/7da3643ab4ea7a97. Report an issue: GitHub.