{"record":{"id":"802126d06fa53fb6","repo":"langchain-ai/deepagents","slug":"schedule-duration-must-be-a-single-value-such-as","errorCode":null,"errorMessage":"schedule duration must be a single value such as '30m'","messagePattern":"schedule duration must be a single value such as '30m'","errorType":"validation","errorClass":"CronJobError","httpStatus":null,"severity":"error","filePath":"libs/talon/deepagents_talon/cron/jobs.py","lineNumber":680,"sourceCode":"    if job.schedule.kind == \"one_shot\":\n        return replace(job, enabled=False, next_run_at=None)\n\n    repeat = job.repeat.claim()\n    if repeat.exhausted:\n        return replace(job, repeat=repeat, enabled=False, next_run_at=None)\n\n    next_run_at = cast(\"datetime\", job.next_run_at)\n    interval = timedelta(minutes=job.schedule.minutes)\n    while next_run_at <= now:\n        next_run_at += interval\n    return replace(job, repeat=repeat, next_run_at=next_run_at)\n\n\ndef _parse_duration_minutes(value: str) -> int:\n    parts = value.split()\n    if len(parts) != 1:\n        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","sourceCodeStart":662,"sourceCodeEnd":698,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/talon/deepagents_talon/cron/jobs.py#L662-L698","documentation":"_parse_duration_minutes parses a cron schedule duration string and requires exactly one token (after whitespace splitting). Passing multiple tokens such as '30 m' or '1h 30m' raises CronJobError; durations must be a single value with an 'm' (minutes) or 'h' (hours) suffix.","triggerScenarios":"Creating a job with schedule 'every 30 m' or '1h 30m' passed to parse(); user-supplied natural-language duration strings that were not normalized to a single token like '30m' before parsing.","commonSituations":"Passing raw user input or LLM-generated schedule text straight into parse without normalization; locale or formatting that inserts a space between number and unit; composing compound durations that the grammar does not support.","solutions":["Normalize the duration to a single token without internal spaces, e.g. '30m' or '2h'.","Convert compound durations to a single unit yourself: 1h 30m -> 90m.","Strip surrounding words: extract just the duration token from phrases like 'every 30 minutes' before calling parse."],"exampleFix":"// before\nschedule = parse(\"every 30 m\")\n// after\ntokens = user_text.split()\ntoken = next(t for t in tokens if t[:-1].isdigit() and t.endswith((\"m\", \"h\")))\nschedule = parse(token)  # \"30m\"","handlingStrategy":"validation","validationCode":"import re\n\ndef normalize_duration(text: str) -> str:\n    m = re.search(r\"(\\d+)([mh])\\b\", text)\n    if not m:\n        raise ValueError(f\"no single m/h duration in {text!r}\")\n    return m.group(1) + m.group(2)","typeGuard":"def is_duration_token(text: str) -> bool:\n    import re\n    return re.fullmatch(r\"\\d+[mh]\", text.strip()) is not None","tryCatchPattern":"try:\n    schedule = parse(duration)\nexcept CronJobError as exc:\n    logger.error(\"bad schedule %r: %s\", duration, exc)\n    schedule = parse(\"30m\")  # or surface to user","preventionTips":["Normalize user/LLM schedule text to a single '<n>m' or '<n>h' token before parse().","Collapse compound durations (1h 30m -> 90m) yourself.","Sanity-check schedules from free-form input with a regex like \\d+[mh] upstream."],"tags":["cron","parsing","schedule","validation"],"backgroundTag":"invalid-schedule-format","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}