langchain-ai/deepagents · error · CronJobError
schedule duration must be a positive integer
Error message
schedule duration must be a positive integer
What it means
CronJobError raised by `_positive_int` in libs/talon/deepagents_talon/cron/jobs.py when the numeric part of a schedule duration is not a decimal integer. `_parse_duration_minutes` strips the 'm'/'h' suffix and delegates here; `str.isdecimal()` must be true. This rejects negatives, signs, whitespace, floats, and non-ASCII digits.
Source
Thrown at libs/talon/deepagents_talon/cron/jobs.py:693
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
def _same_origin_scope(left: CronOrigin, right: CronOrigin) -> bool:
return left.conversation_id == right.conversation_id and left.channel == right.channel
def _coerce_utc(value: datetime | None = None) -> datetime:
if value is None:
return datetime.now(UTC)
if value.tzinfo is None:
return value.replace(tzinfo=UTC)
return value.astimezone(UTC)
View on GitHub (pinned to a1af029e6e)
Solutions
- Use a plain non-negative decimal integer before the unit: '5m', '60m', '2h'.
- Convert fractional hours to whole minutes (e.g. '1.5h' -> '90m').
- Strip whitespace and invisible characters from the schedule string before passing it in.
Example fix
// before
parse("1.5h", ...)
parse(" 30m", ...)
// after
parse("90m", ...)
parse("30m", ...) Defensive patterns
Strategy: validation
Validate before calling
def validate_duration_number(text: str) -> bool:
unit, num = text[-1:], text[:-1]
return unit in ("m", "h") and num.isdecimal() and int(num) >= 1 Type guard
def is_decimal_duration(text: str) -> bool:
return isinstance(text, str) and len(text) > 1 and text[:-1].isdecimal() Try / catch
try:
job = parse(schedule)
except CronJobError as exc:
raise ValueError(f"schedule {schedule!r} must be an integer like '30m' or '2h'") from exc Prevention
- Strip whitespace before passing duration strings.
- Avoid floats like '1.5h' — precompute '90m'.
- Beware copy-paste characters (en-dash, non-breaking space) that break isdecimal().
When it happens
Trigger: Passing a schedule like '-5m', ' 10m', '1.5h', '+3h', or 'abc' to `parse`. After stripping the unit suffix, the remaining text fails `isdecimal()` and this error is raised.
Common situations: Hand-edited config files with stray spaces or typo characters; floats used for sub-minute precision (e.g. '0.5h'); copy-paste artifacts like en-dashes or non-breaking spaces in the duration.
Related errors
- cron schedules must be at least 1 minute
- schedule must look like 'in 30m' or 'every 15m'
- repeat cap must be at least 1
- repeat completed count cannot be negative
- repeat cap is only valid for recurring jobs
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/baa9e8650b3e71aa.
Report an issue: GitHub.