{"record":{"id":"de7ad20cbff168ba","repo":"NousResearch/hermes-agent","slug":"cron-expressions-require-croniter-package-insta","errorCode":null,"errorMessage":"Cron expressions require 'croniter' package. Install with: pip install croniter","messagePattern":"Cron expressions require 'croniter' package\\. Install with: pip install croniter","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"cron/jobs.py","lineNumber":651,"sourceCode":"    \n    # \"every X\" pattern → recurring interval\n    if schedule_lower.startswith(\"every \"):\n        duration_str = schedule[6:].strip()\n        minutes = parse_duration(duration_str)\n        return {\n            \"kind\": \"interval\",\n            \"minutes\": minutes,\n            \"display\": f\"every {minutes}m\"\n        }\n    \n    # Check for cron expression (5 or 6 space-separated fields)\n    # Cron fields: minute hour day month weekday [year]\n    parts = schedule.split()\n    if len(parts) >= 5 and all(\n        re.match(r'^[\\d\\*\\-,/]+$', p) for p in parts[:5]\n    ):\n        if not _ensure_croniter():\n            raise ValueError(\"Cron expressions require 'croniter' package. Install with: pip install croniter\")\n        # Validate cron expression\n        try:\n            croniter(schedule)\n        except Exception as e:\n            raise ValueError(f\"Invalid cron expression '{schedule}': {e}\")\n        return {\n            \"kind\": \"cron\",\n            \"expr\": schedule,\n            \"display\": schedule\n        }\n    \n    # ISO timestamp (contains T or looks like date)\n    if 'T' in schedule or re.match(r'^\\d{4}-\\d{2}-\\d{2}', schedule):\n        try:\n            # Parse and validate\n            dt = datetime.fromisoformat(schedule.replace('Z', '+00:00'))\n            # Make naive timestamps timezone-aware at parse time so the stored\n            # value doesn't depend on the system timezone matching at check time.","sourceCodeStart":633,"sourceCodeEnd":669,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/cron/jobs.py#L633-L669","documentation":"ValueError raised in parse_schedule: the string was classified as a cron expression (5+ space-separated fields all matching ^[\\d*\\-,/]+$), but the croniter package needed to validate cron expressions is not installed and could not be auto-ensured by _ensure_croniter(). Interval and ISO-timestamp schedules do not need croniter; only the cron-expression branch does.","triggerScenarios":"create_job(schedule='0 9 * * *') in an environment where croniter is absent (not in requirements, stripped slim install, or a broken import caught by _ensure_croniter).","commonSituations":"Minimal/slim deployments that excluded the optional croniter dependency; a corrupted venv; croniter removed during an upgrade.","solutions":["Install croniter into the running interpreter: pip install croniter","If you cannot install, use an equivalent the parser supports without croniter, e.g. an ISO one-shot timestamp — though for recurring schedules croniter is effectively required"],"exampleFix":"# before\ncreate_job(schedule=\"0 9 * * *\")\n# ValueError: Cron expressions require 'croniter' package.\n\n# after\npython -m pip install croniter\ncreate_job(schedule=\"0 9 * * *\")","handlingStrategy":"fallback","validationCode":"import importlib.util\n\ndef croniter_available() -> bool:\n    return importlib.util.find_spec(\"croniter\") is not None\n\nif not croniter_available() and looks_like_cron(expr):\n    raise SystemExit(\"pip install croniter (required for cron expressions)\")","typeGuard":null,"tryCatchPattern":"try:\n    parsed = parse_schedule(\"0 9 * * *\")\nexcept ValueError as e:\n    if \"croniter\" in str(e):\n        subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"croniter\"], check=True)\n        parsed = parse_schedule(\"0 9 * * *\")\n    else:\n        raise","preventionTips":["Install croniter in any deployment that accepts cron expressions","Pre-check find_spec('croniter') when the schedule has 5+ cron-ish fields","Keep croniter in the pinned requirements so slim installs don't drop it"],"tags":["cron","dependencies","croniter","scheduling"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}