{"record":{"id":"89c5321040da035d","repo":"HKUDS/Vibe-Trading","slug":"cron-field-atom-r-is-out-of-range-expected-low","errorCode":null,"errorMessage":"cron field {atom!r} is out of range; expected {low}-{high}","messagePattern":"cron field (.+?) is out of range; expected (.+?)-(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/scheduled_research/models.py","lineNumber":66,"sourceCode":"        return\n    if _CRON_STEP_RE.fullmatch(part):\n        value = int(part[2:])\n        if not low <= value <= high:\n            raise ValueError(f\"cron field {part!r} is out of range; expected {low}-{high}\")\n        return\n    for atom in part.split(\",\"):\n        match = _CRON_ATOM_RE.fullmatch(atom)\n        if match is None:\n            raise ValueError(\n                f\"cron field {part!r} is not valid; each field must be *, */n, \"\n                f\"or a comma-separated list of numbers and low-high ranges\"\n            )\n        start = int(match.group(1))\n        end = int(match.group(2)) if match.group(2) is not None else start\n        if start > end:\n            raise ValueError(f\"cron range {atom!r} is reversed; expected low-high\")\n        if start < low or end > high:\n            raise ValueError(f\"cron field {atom!r} is out of range; expected {low}-{high}\")\n\n\ndef parse_cron_field(part: str, low: int, high: int) -> Optional[Set[int]]:\n    \"\"\"Expand one validated cron field into its matching values.\n\n    Kept beside :func:`validate_schedule` so the accepted grammar and the\n    executor's evaluation of it can never drift apart.\n\n    Args:\n        part: One whitespace-delimited cron field (already validated).\n        low: Inclusive lower bound of the field.\n        high: Inclusive upper bound of the field.\n\n    Returns:\n        The set of matching integer values, or ``None`` for the ``*`` wildcard.\n    \"\"\"\n    if part == \"*\":\n        return None","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/scheduled_research/models.py#L48-L84","documentation":"After a range atom parses, both its endpoints must lie within the field's bounds (minutes 0-59, hours 0-23, day-of-month 1-31, month 1-12, day-of-week 0-6). A well-formed but out-of-bounds atom such as minute 60 or month 13 is rejected so the executor never computes impossible fire times.","triggerScenarios":"validate_schedule('61 * * * *') (minute 61), '0 0 32 * *' (day 32), '0 0 * 13 *' (month 13), or ranges like '0 0 * * 0-7' where 7 exceeds the 0-6 day-of-week bound.","commonSituations":"Day-of-week confusion: cron systems differ on whether Sunday is 0 or 7 and whether the bound is 0-6 or 1-7; this parser uses 0-6. Also hand-typed schedules with off-by-one month numbers (1-12, not 0-11).","solutions":["Check each atom against the field bounds; here day-of-week is 0-6 with Sunday=0, month is 1-12.","Replace 7 with 0 for Sunday (or just list '0,6' for weekends).","Run validate_schedule on every schedule before storing the job."],"exampleFix":"# before\nvalidate_schedule('0 0 * * 1-7')\n# after\nvalidate_schedule('0 0 * * 0-6')","handlingStrategy":"validation","validationCode":"BOUNDS = [(0,59),(0,23),(1,31),(1,12),(0,6)]\nfor part, (lo, hi) in zip(schedule.split(), BOUNDS):\n    for atom in part.split(','):\n        for tok in atom.split('-'):\n            assert lo <= int(tok) <= hi, f'{atom} out of {lo}-{hi}'","typeGuard":null,"tryCatchPattern":"try:\n    validate_schedule(schedule)\nexcept ValueError as e:\n    return bad_request(str(e))","preventionTips":["Day-of-week is 0-6 with Sunday=0 here; month is 1-12.","Validate schedules before persisting jobs."],"tags":["python","cron","validation","scheduler","out-of-range"],"backgroundTag":"cron-expression-invalid","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}