Cron Atlas

Kubernetes error TZ= or CRON_TZ= in the schedule

cannot use TZ or CRON_TZ in schedule, use timeZone field instead

spec.schedule: Invalid value: "CRON_TZ=Europe/London 0 9 * * *": cannot use TZ or CRON_TZ in schedule, use timeZone field instead
An existing CronJob with the prefix that also sets .spec.timeZone
spec.schedule: Invalid value: "CRON_TZ=Europe/London 0 9 * * *": cannot use both timeZone field and TZ or CRON_TZ in schedule

Message text from validation.go in Kubernetes’ CronJob validation. Which expressions fail follows the tester’s own engine.

What it means

Kubernetes validation rejects any schedule that contains TZ, which catches both TZ= and CRON_TZ= prefixes, even though the parser underneath understands them. The zone goes in its own field, .spec.timeZone, which takes an IANA name such as Europe/London.

A CronJob that already had a prefix before the check arrived can still be updated while it keeps the prefix. Adding .spec.timeZone to it as well gives the second message.

Rejected expressions and their fixes

Each expression opens in the tester. The message under a rejected one is built the way the source above builds it.

  1. RejectedCRON_TZ=Europe/London 0 9 * * *cannot use TZ or CRON_TZ in schedule, use timeZone field instead
    Use
    0 9 * * *At 09:00 (Europe/London).
    spec:
      schedule: "0 9 * * *"
      timeZone: "Europe/London"

    09:00 London time every day.

  2. RejectedTZ=America/New_York 30 6 * * 1-5cannot use TZ or CRON_TZ in schedule, use timeZone field instead
    Use
    30 6 * * 1-5At 06:30, Monday through Friday (America/New_York).
    spec:
      schedule: "30 6 * * 1-5"
      timeZone: "America/New_York"

    06:30 New York time on weekdays.

Questions

Which Kubernetes version has .spec.timeZone?
It became stable in Kubernetes 1.27.
What zone does a CronJob use without .spec.timeZone?
The local zone of the kube-controller-manager that runs the CronJob controller. Set .spec.timeZone rather than depend on it.

Other Kubernetes errors

Reference