{"record":{"id":"43d748140623af84","repo":"langchain-ai/deepagents","slug":"repeat-cap-is-only-valid-for-recurring-jobs","errorCode":null,"errorMessage":"repeat cap is only valid for recurring jobs","messagePattern":"repeat cap is only valid for recurring jobs","errorType":"validation","errorClass":"CronJobError","httpStatus":null,"severity":"error","filePath":"libs/talon/deepagents_talon/cron/jobs.py","lineNumber":363,"sourceCode":"    ) -> CronJob:\n        \"\"\"Create and persist a cron job.\n\n        Args:\n            prompt: Prompt passed to the agent when the job fires.\n            schedule: Job schedule.\n            origin: Conversation that receives results.\n            name: Human-readable label.\n            repeat_times: Optional cap for recurring jobs.\n            now: Creation time override for deterministic tests.\n\n        Returns:\n            Created job record.\n        \"\"\"\n        current = _coerce_utc(now)\n        repeat = CronRepeat(times=repeat_times)\n        if schedule.kind == \"one_shot\" and repeat_times is not None:\n            msg = \"repeat cap is only valid for recurring jobs\"\n            raise CronJobError(msg)\n        job = CronJob(\n            id=uuid.uuid4().hex[:12],\n            assistant_id=self.assistant_id,\n            name=name,\n            prompt=prompt,\n            schedule=schedule,\n            repeat=repeat,\n            enabled=True,\n            created_at=current,\n            next_run_at=schedule.next_after(current),\n            last_run_at=None,\n            last_status=None,\n            last_error=None,\n            origin=origin,\n        )\n        jobs = [*self.list_jobs(), job]\n        self._write_jobs(jobs)\n        return job","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/talon/deepagents_talon/cron/jobs.py#L345-L381","documentation":"create_job raises this CronJobError when a one-shot schedule ('in ...') is combined with a repeat cap (repeat_times is not None). Repeat caps only make sense for recurring ('every ...') jobs, since a one-shot job runs exactly once and can never repeat; the library rejects the contradictory configuration up front.","triggerScenarios":"Calling create_job(name=..., prompt=..., schedule=<one_shot CronSchedule>, repeat_times=3). Also constructing via parse('in 30m') while passing a non-None repeat_times from a shared code path that always forwards a cap.","commonSituations":"A UI form that always shows a repeat-count field regardless of schedule type; refactors where a default repeat_times=1 leaked into one-shot creation; misreading None (unlimited) vs 0 as the way to say 'no cap' and passing a number alongside a one-shot schedule.","solutions":["Pass repeat_times=None when the schedule is one-shot","Only set repeat_times when schedule.kind == 'recurring'","Branch on the parsed schedule's kind before calling create_job","Catch CronJobError and drop the cap (retry with repeat_times=None) if the schedule is one-shot"],"exampleFix":"// before\njob = store.create_job(name=\"ping\", prompt=\"...\", schedule=CronSchedule.parse(\"in 30m\"), repeat_times=3)\n// after\njob = store.create_job(name=\"ping\", prompt=\"...\", schedule=CronSchedule.parse(\"in 30m\"), repeat_times=None)\n# caps only for recurring:\njob = store.create_job(name=\"ping\", prompt=\"...\", schedule=CronSchedule.parse(\"every 15m\"), repeat_times=3)","handlingStrategy":"try-catch","validationCode":"def is_recurring(schedule) -> bool:\n    return getattr(schedule, \"kind\", None) == \"recurring\"\n\nsafe_repeat_times = repeat_times if is_recurring(schedule) else None\njob = store.create_job(..., schedule=schedule, repeat_times=safe_repeat_times)","typeGuard":"def is_recurring_schedule(schedule: object) -> bool:\n    return getattr(schedule, \"kind\", None) == \"recurring\"","tryCatchPattern":"try:\n    job = store.create_job(..., schedule=schedule, repeat_times=repeat_times)\nexcept CronJobError as exc:\n    if \"repeat cap\" in str(exc):\n        job = store.create_job(..., schedule=schedule, repeat_times=None)\n    else:\n        raise","preventionTips":["Gate the repeat-count form field on schedule kind being 'recurring'","Default repeat_times to None everywhere; only set it for 'every ...' schedules","Branch on schedule.kind before composing create_job arguments","Never send a numeric cap alongside a one-shot schedule from shared submission code"],"tags":["validation","cron","api-misuse"],"backgroundTag":"repeat-cap-on-one-shot-job","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}