Skip to main content
A scheduler manifest is the unit of work for every command in this group. It names one scheduler blob and one revision, and lists every schedule that belongs on that revision. There is no per-schedule manifest and no default path — -f/--file is required everywhere, and the file it names is loaded before anything else happens. The file is parsed by extension: .yaml, .yml and .json all work, and the same manifest written in YAML or in JSON loads identically. An unsupported extension is FORMAT_UNSUPPORTED; a file that does not parse is FORMAT_PARSE_ERROR.

The shared base

scheduler_blob_deployment is the second manifest type over the shared base the workflow manifest introduces. The base is parsed and validated by itself, before the body is looked at, and type is what selects the body — so these four fields mean here exactly what they mean there.
The blob’s shape is confirmed before any engine call: a scheduler manifest pointed at a workflow blob stops with BLOB_NOT_WORKFLOW — one shared resolver raises that code for every group, and its message names both the shape found and the shape expected. A scheduler blob is created in phase managed and holds a single revision, always, so revision: latest is the normal value and names the one revision there is. Pinning a UUID is legal and does exactly what it does in the workflow group.

The scheduler_blob_deployment body

One key: schedules, a list. Unlike the workflow body’s definitions, an empty list is valid — a revision holding no schedules is an ordinary state, and an empty schedules: [] is precisely the document pull writes for one. A missing key is still MANIFEST_INVALID: absent is a manifest that says nothing about schedules, empty is one that says there are none. The CLI carries every time and date field through as an opaque string and checks none of their contents, so the naive/UTC split above is the platform’s rule, enforced where the schedule is written rather than where it is authored. Unlisted keys are ignored rather than rejected, so a typo’d field name is silently inert. There is no schema beyond what is described here.

repeat decides which timing field exists

repeat gives exactly one of cron_expression and invocation_time meaning, and the manifest must carry that one and only that one. A recurring_cron entry without a cron_expression, or a one_time entry without an invocation_time, is MANIFEST_INVALID. So is an entry carrying both. Refusing both is worth the extra rule. The likeliest way to arrive there is the half-finished edit that flips repeat and leaves the old kind’s field behind — and the field left behind can never take effect, never be reported as differing, and can never be removed from a deployed schedule either: update_schedule sets only the keys it is sent and rejects a null, so a record flipped from recurring_cron to one_time keeps its stale cron_expression for good. Only the field repeat gives meaning to is compared, by diff and deploy alike.

The target block

target names a workflow blob, not the scheduler blob the manifest is about. blob, revision, session and workflow are required; type, input_data and description are not. input_data is the one field nothing checks until the schedule fires. The scheduler’s own schema types it as a bare array, so create_schedule accepts any list at all; the item shape — {"alias": "<component alias>", "value": {"type": …}}, documented under Create Execution — is enforced by create_execution at fire time, where a violation surfaces as an invocation_error on the schedule’s execution history rather than as a failed deploy.

Four constraints, checked before anything is written

These four are answered offline, at load time, before a single schedule is created or updated. They are checked locally rather than left to the server for one reason: deploy writes entries in order, so a manifest whose second entry breaks a rule the platform enforces would deploy the first and then fail — leaving a half-deployed set that is already firing on its cron. alias is required on every entry, which the platform does not require of a schedule — it is the manifest’s identity for one, and what makes a second deploy an update rather than a duplicate. cron_expression and timezone are the one class of failure the CLI cannot catch beforehand. Neither is constrained by any schema, and the CLI passes both through as opaque strings. They are validated when the schedule is written:
  • The platform itself answers the two cron mistakes that are common and badly reported downstream — an expression that is not exactly six space-separated fields, and one where day-of-month and day-of-week are not exactly one ? between them. Both come back as invalid_cron_expression. The plausible-looking 0 9 * * MON-FRI * is the second of those; 0 9 ? * MON-FRI * is the working form.
  • Everything else — ranges, steps, month and day names, out-of-range values, and the timezone, which is handed straight to the scheduling service as its ScheduleExpressionTimezone — is the scheduling service’s own rejection, surfaced with its message.
So a bad cron or timezone on a later entry can leave earlier entries deployed, which is the gap the constraints above exist to keep as small as possible. Check the syntax against cron expressions before deploying a set.

A worked example

A scheduler blob acme-corp/checkout-ops carrying two schedules against the workflow blob acme-corp/checkout: a recurring one that runs every morning in New York time against a session it shares with every other run, and a one-time launch pinned to a specific revision, with input data and an execution description.
Both files load to the same manifest. The first entry’s blob: checkout is bare and inherits acme-corp from the manifest’s own blob; the second qualifies the same org explicitly, which is equivalent. The first entry omits type in its target, which is the same as declaring workflow. The second entry’s pinned target.revision is worth one note. latest and a pinned UUID both reach the platform as a resolved revision id, so nothing in a stored schedule records which of the two the manifest wrote. pull reads that back from the manifest entry it is refreshing, matched by alias — so a pin survives a pull instead of being flattened to latest the moment it happens to name the leading revision. A schedule the manifest never carried has no such record: it comes back as latest when its target revision still leads the blob, and as a literal UUID when it does not.

Errors

Every code above, with its remediation, is in Error codes.

See also

  • Scheduler overview — the two blobs one deploy touches, and the four commands that manage them.
  • Workflow manifest — the same shared base, with the workflow_blob_deployment body over it.
  • Scheduler blob type — cron syntax, timezones, date windowing, alias grammar and schedule states, as the platform defines them.
  • Concepts — why a manifest is revision-scoped, and why drift in this group is not inert.