langchain-ai/deepagents · error · CronJobError

schedule duration must be a single value such as '30m'

Error message

schedule duration must be a single value such as '30m'

What it means

_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.

Source

Thrown at libs/talon/deepagents_talon/cron/jobs.py:680

    if job.schedule.kind == "one_shot":
        return replace(job, enabled=False, next_run_at=None)

    repeat = job.repeat.claim()
    if repeat.exhausted:
        return replace(job, repeat=repeat, enabled=False, next_run_at=None)

    next_run_at = cast("datetime", job.next_run_at)
    interval = timedelta(minutes=job.schedule.minutes)
    while next_run_at <= now:
        next_run_at += interval
    return replace(job, repeat=repeat, next_run_at=next_run_at)


def _parse_duration_minutes(value: str) -> int:
    parts = value.split()
    if len(parts) != 1:
        msg = "schedule duration must be a single value such as '30m'"
        raise CronJobError(msg)
    text = parts[0]
    if text.endswith("m"):
        return _positive_int(text[:-1])
    if text.endswith("h"):
        return _positive_int(text[:-1]) * 60
    msg = "schedule duration must use 'm' for minutes or 'h' for hours"
    raise CronJobError(msg)


def _positive_int(value: str) -> int:
    if not value.isdecimal():
        msg = "schedule duration must be a positive integer"
        raise CronJobError(msg)
    number = int(value)
    if number < MIN_GRANULARITY_MINUTES:
        msg = "schedule duration must be at least 1 minute"
        raise CronJobError(msg)
    return number

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Normalize the duration to a single token without internal spaces, e.g. '30m' or '2h'.
  2. Convert compound durations to a single unit yourself: 1h 30m -> 90m.
  3. Strip surrounding words: extract just the duration token from phrases like 'every 30 minutes' before calling parse.

Example fix

// before
schedule = parse("every 30 m")
// after
tokens = user_text.split()
token = next(t for t in tokens if t[:-1].isdigit() and t.endswith(("m", "h")))
schedule = parse(token)  # "30m"
Defensive patterns

Strategy: validation

Validate before calling

import re

def normalize_duration(text: str) -> str:
    m = re.search(r"(\d+)([mh])\b", text)
    if not m:
        raise ValueError(f"no single m/h duration in {text!r}")
    return m.group(1) + m.group(2)

Type guard

def is_duration_token(text: str) -> bool:
    import re
    return re.fullmatch(r"\d+[mh]", text.strip()) is not None

Try / catch

try:
    schedule = parse(duration)
except CronJobError as exc:
    logger.error("bad schedule %r: %s", duration, exc)
    schedule = parse("30m")  # or surface to user

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/802126d06fa53fb6. Report an issue: GitHub.