{"record":{"id":"cea932d11f76c6fa","repo":"langchain-ai/deepagents","slug":"schedule-duration-must-be-at-least-1-minute","errorCode":null,"errorMessage":"schedule duration must be at least 1 minute","messagePattern":"schedule duration must be at least 1 minute","errorType":"validation","errorClass":"CronJobError","httpStatus":null,"severity":"error","filePath":"libs/talon/deepagents_talon/cron/jobs.py","lineNumber":697,"sourceCode":"        msg = \"schedule duration must be a single value such as '30m'\"\n        raise CronJobError(msg)\n    text = parts[0]\n    if text.endswith(\"m\"):\n        return _positive_int(text[:-1])\n    if text.endswith(\"h\"):\n        return _positive_int(text[:-1]) * 60\n    msg = \"schedule duration must use 'm' for minutes or 'h' for hours\"\n    raise CronJobError(msg)\n\n\ndef _positive_int(value: str) -> int:\n    if not value.isdecimal():\n        msg = \"schedule duration must be a positive integer\"\n        raise CronJobError(msg)\n    number = int(value)\n    if number < MIN_GRANULARITY_MINUTES:\n        msg = \"schedule duration must be at least 1 minute\"\n        raise CronJobError(msg)\n    return number\n\n\ndef _same_origin_scope(left: CronOrigin, right: CronOrigin) -> bool:\n    return left.conversation_id == right.conversation_id and left.channel == right.channel\n\n\ndef _coerce_utc(value: datetime | None = None) -> datetime:\n    if value is None:\n        return datetime.now(UTC)\n    if value.tzinfo is None:\n        return value.replace(tzinfo=UTC)\n    return value.astimezone(UTC)\n\n\ndef _format_optional_time(value: datetime | None) -> str | None:\n    return None if value is None else _format_time(value)\n","sourceCodeStart":679,"sourceCodeEnd":715,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/talon/deepagents_talon/cron/jobs.py#L679-L715","documentation":"CronJobError raised by `_positive_int` in libs/talon/deepagents_talon/cron/jobs.py when a parsed schedule duration is below MIN_GRANULARITY_MINUTES (1 minute). The scheduler's finest tick granularity is one minute, so sub-minute schedules are meaningless and rejected rather than silently rounded.","triggerScenarios":"Passing '0m', '0h', or any duration that parses to a value < 1 minute (e.g. '0h' equals 0 minutes) to `parse`. The integer parses fine but fails the `number < MIN_GRANULARITY_MINUTES` check.","commonSituations":"Trying to schedule a job to run 'immediately' with '0m'; templated durations where a variable defaulted to 0; porting sub-minute intervals from other systems.","solutions":["Use a duration of at least 1 minute ('1m' or more).","If the job should fire immediately, invoke the job directly instead of scheduling it with a 0 duration.","Audit templates/config so duration variables cannot evaluate to 0."],"exampleFix":"// before\nparse(\"0m\", ...)\n// after\nparse(\"1m\", ...)","handlingStrategy":"validation","validationCode":"def validate_min_duration(text: str) -> bool:\n    num = int(text[:-1]) if text[:-1].isdecimal() else 0\n    minutes = num if text.endswith(\"m\") else num * 60\n    return minutes >= 1","typeGuard":null,"tryCatchPattern":"try:\n    job = parse(schedule)\nexcept CronJobError as exc:\n    if \"at least 1 minute\" in str(exc):\n        schedule = \"1m\"  # or run the job immediately\n    else:\n        raise","preventionTips":["Never use '0m'/'0h'; minimum schedule is '1m'.","For immediate runs, call the job directly instead of a 0-duration schedule.","Guard templated duration variables against defaulting to 0."],"tags":["cron","validation","minimum-value"],"backgroundTag":"invalid-duration-format","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}