langchain-ai/deepagents · error · ValueError

tick_seconds must be positive

Error message

tick_seconds must be positive

What it means

ValueError raised in `Scheduler.__init__` (libs/talon/deepagents_talon/cron/scheduler.py:50) when `tick_seconds` is zero or negative. The ticker loop sleeps `tick_seconds` between iterations, so a non-positive value would busy-loop or misbehave. The guard fires at construction time before any asyncio task starts.

Source

Thrown at libs/talon/deepagents_talon/cron/scheduler.py:50

        run_job: Callback that invokes the agent for a claimed job.
        deliver_result: Callback that delivers non-silent job output.
        tick_seconds: Interval between due-job scans.
        now: Clock override for deterministic tests.
    """

    def __init__(
        self,
        *,
        store: CronJobStore,
        run_job: RunCronJob,
        deliver_result: DeliverCronResult,
        tick_seconds: float = DEFAULT_TICK_SECONDS,
        now: NowFactory | None = None,
    ) -> None:
        """Initialize the scheduler without starting the ticker."""
        if tick_seconds <= 0:
            msg = "tick_seconds must be positive"
            raise ValueError(msg)
        self.store = store
        self.run_job = run_job
        self.deliver_result = deliver_result
        self.tick_seconds = tick_seconds
        self.now = now or (lambda: datetime.now(UTC))
        self._task: asyncio.Task[None] | None = None
        self._stopped = asyncio.Event()

    async def start(self) -> None:
        """Start the scheduler ticker."""
        if self._task is not None and not self._task.done():
            return
        self._stopped.clear()
        self._task = asyncio.create_task(self._ticker(), name="talon:cron")

    async def stop(self) -> None:
        """Stop the scheduler ticker."""
        self._stopped.set()

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Pass a positive float, e.g. `tick_seconds=1.0` (or omit it to use DEFAULT_TICK_SECONDS).
  2. Clamp the value before constructing: `max(tick_seconds, 0.1)`.
  3. Fix the config/env source so it yields a positive number instead of 0.

Example fix

// before
Scheduler(store, run_job, deliver, tick_seconds=float(os.environ.get("TICK_SECONDS", 0)))
// after
Scheduler(store, run_job, deliver, tick_seconds=max(float(os.environ.get("TICK_SECONDS", "1")), 0.1))
Defensive patterns

Strategy: validation

Validate before calling

tick = float(raw_tick)
if tick <= 0:
    raise ValueError(f"tick_seconds must be positive, got {tick}")
scheduler = Scheduler(store, run_job, deliver, tick_seconds=tick)

Try / catch

try:
    scheduler = Scheduler(store, run_job, deliver, tick_seconds=tick)
except ValueError as exc:
    logger.error("bad tick_seconds %r: %s", tick, exc)
    scheduler = Scheduler(store, run_job, deliver)  # fall back to default

Prevention

When it happens

Trigger: Constructing `Scheduler(store, run_job, deliver_result, tick_seconds=0)` or a negative value; computing tick_seconds from config where a divisor or env value resolved to 0.

Common situations: Env var like TICK_SECONDS unset/empty then coerced to 0; config math like `60/interval` with a huge interval rounding to 0; passing 0 hoping for 'as fast as possible'.

Understand the failure class

Background: "Invalid configuration value" and "Unsupported/Unknown setting value" errors: why libraries reject your config strings, numbers, and types — this error's family across 30 libraries.

Related errors


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