HKUDS/Vibe-Trading · error · ValueError
cron range is reversed; expected low-high
Error message
cron range {atom!r} is reversed; expected low-high What it means
Within a cron field atom, a range low-high must have low <= high. A reversed range like 5-1 matches the atom grammar but denotes an empty set of values, which is almost always an authoring mistake, so it is rejected explicitly rather than silently matching nothing.
Solutions
- Split wrap-around ranges into explicit lists: '22-23,0-2' for 22:00-02:00, '0,5-6' for Sunday plus Fri-Sat.
- Sort generated bounds before formatting a range.
- Prefer listing individual values when unsure.
Example fix
# before
validate_schedule('0 22-2 * * *')
# after
validate_schedule('0 22-23,0-2 * * *') Defensive patterns
Strategy: validation
Validate before calling
for atom in part.split(','):
if '-' in atom:
lo, hi = map(int, atom.split('-'))
assert lo <= hi, f'reversed range: {atom}'
validate_schedule(schedule) Try / catch
try:
validate_schedule(schedule)
except ValueError as e:
return {'error': str(e)}, 400 Prevention
- Split wrap-around ranges into explicit lists (e.g. '22-23,0-2').
- Sort generated range bounds before formatting.
When it happens
Trigger: validate_schedule('0 0 * * 5-1') (Friday-to-Monday style wrap), '50-10 * * * *' for minutes, or ranges generated by min/max arguments passed in the wrong order.
Common situations: Trying to express a wrap-around range (e.g. 'weekend plus Monday' or '10pm-2am') which standard cron cannot express as a single range; programmatic range building with swapped bounds.
Related errors
- cron field is out of range; expected
- cron field is not valid; each field must be *, */n, or a…
- cron field is out of range; expected
- interval is too large; expected at most 15 digits of…
- schedule must be a non-empty string
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/450e6d50e9094e38.
Report an issue: GitHub.
Appendix: source
Thrown at agent/src/scheduled_research/models.py:64
"""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.
Kept beside :func:`validate_schedule` so the accepted grammar and the
executor's evaluation of it can never drift apart.
Args:
part: One whitespace-delimited cron field (already validated).
low: Inclusive lower bound of the field.
high: Inclusive upper bound of the field.
Returns:
The set of matching integer values, or ``None`` for the ``*`` wildcard.
"""View on GitHub (pinned to 80ffdda44c)