langchain-ai/deepagents · error · CronJobError

repeat cap must be at least 1

Error message

repeat cap must be at least 1

What it means

CronRepeat.__post_init__ validates that the optional repeat cap (times) is at least 1 when provided; passing 0 or a negative number raises this CronJobError immediately at dataclass construction. A repeat cap of 0 or less is meaningless — a recurring job must run at least once per cap, so the library refuses to construct the invalid state.

Source

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


@dataclass(frozen=True, slots=True)
class CronRepeat:
    """Optional cap for recurring cron jobs.

    Args:
        times: Maximum scheduled attempts, or `None` for unlimited recurrence.
        completed: Number of intervals already claimed for execution.
    """

    times: int | None = None
    completed: int = 0

    def __post_init__(self) -> None:
        """Validate repeat cap values."""
        if self.times is not None and self.times < 1:
            msg = "repeat cap must be at least 1"
            raise CronJobError(msg)
        if self.completed < 0:
            msg = "repeat completed count cannot be negative"
            raise CronJobError(msg)

    def claim(self) -> CronRepeat:
        """Return repeat state after claiming one scheduled attempt.

        Returns:
            Updated repeat state.
        """
        return replace(self, completed=self.completed + 1)

    @property
    def exhausted(self) -> bool:
        """Whether the repeat cap has been reached."""
        return self.times is not None and self.completed >= self.times

    def to_dict(self) -> CronRepeatDict:

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Pass repeat_times >= 1, or pass None to indicate an uncapped recurring job
  2. Replace 0-as-sentinel logic with None so validation passes and semantics are correct
  3. Validate user-supplied repeat counts (int and >= 1) before constructing CronRepeat or calling create_job/edit_job
  4. Catch CronJobError around create_job/edit_job and re-prompt or clamp the value

Example fix

// before
repeat = CronRepeat(times=0)  # raises
// after
repeat = CronRepeat(times=None)  # unlimited
# or a real cap
repeat = CronRepeat(times=1)
Defensive patterns

Strategy: validation

Validate before calling

def is_valid_repeat_cap(times) -> bool:
    return times is None or (isinstance(times, int) and times >= 1)

if not is_valid_repeat_cap(repeat_times):
    raise ValueError("repeat cap must be None (unlimited) or an integer >= 1")

Type guard

def is_repeat_cap(value: object) -> bool:
    return value is None or (isinstance(value, int) and not isinstance(value, bool) and value >= 1)

Try / catch

try:
    job = store.create_job(..., repeat_times=times)
except CronJobError as exc:
    if "repeat cap" in str(exc):
        job = store.create_job(..., repeat_times=None)
    else:
        raise

Prevention

When it happens

Trigger: Constructing CronRepeat(times=0) or CronRepeat(times=-1) directly, or calling create_job/edit_job with repeat_times=0 or repeat_times=<negative int> on a recurring schedule.

Common situations: Using 0 as a 'no repeat' sentinel (the library expects None for unlimited instead); decrementing a counter in a loop until it hits 0 before passing it; config files where a cap was omitted and a 0 default filled in; off-by-one math producing -1.

Related errors


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