too many missed start times: The CronJob controller lost track of the schedule and stopped
Cannot determine if job needs to be started: too many missed start times means the controller found more than 100 missed schedules and refuses to guess. The CronJob stops running until its status is reset.
Applies to: All Kubernetes versions
What it means
The CronJob controller works by comparing the schedule against the last scheduled time recorded in its status. If it finds more than 100 missed start times since then, it gives up rather than firing a hundred Jobs at once, and logs this message. The two ways to get here are quite different. Either the controller was genuinely unable to run — a control plane outage, or a suspended CronJob left suspended past 100 intervals — or, more commonly, startingDeadlineSeconds is unset and a frequent schedule drifted far enough that the controller counted a large backlog. Either way the CronJob is stuck and will not resume on its own.
Most common causes
- The CronJob was suspended for longer than 100 schedule intervals and then resumed.
- The control plane or the controller manager was unavailable for a long period.
- A frequent schedule combined with an unset
startingDeadlineSeconds, so every missed interval counts. - Clock skew between the controller and reality.
- The CronJob was created with a
lastScheduleTimefar in the past, for example when restored from a backup. - A very short schedule, such as every minute, where 100 misses is under two hours.
How to diagnose it
- Read the CronJob's status and the controller's events:
kubectl describe cronjob CRONJOB. - Check
lastScheduleTime:kubectl get cronjob CRONJOB -o jsonpath='{.status.lastScheduleTime}'. A distant timestamp confirms it. - Check whether the CronJob is suspended:
kubectl get cronjob CRONJOB -o jsonpath='{.spec.suspend}'. - Check
startingDeadlineSeconds— if it is unset, the controller counts every missed interval back to the last schedule. - Check control plane availability over the affected period.
How to fix it
- Set
startingDeadlineSecondsto a value comfortably shorter than the schedule interval. This bounds how far back the controller looks and prevents the backlog from accumulating at all. - Clear the stale status so the controller resumes — recreating the CronJob is the simplest reliable way.
- Unsuspend the CronJob if that is why it stopped, and expect to clear the status as well if it was suspended a long time.
- Correct clock skew on the control plane.
- Choose
concurrencyPolicydeliberately, so that a resumed schedule does not start overlapping Jobs.
Notes
Setting startingDeadlineSeconds is the preventive fix and it is unset by default, which means every CronJob is exposed to this until someone sets it. A value slightly under the schedule interval is the usual choice.
Related
- BackoffLimitExceeded — The Job's pods failed too many times
- Completed — All containers exited successfully