windmill-labs/windmill · error

Invalid schedule or timezone: ${formatToolError(error)}

Error message

Invalid schedule or timezone: ${formatToolError(error)}

What it means

create_schedule validates the cron expression and timezone server-side via ScheduleService.previewSchedule before creating anything. If that preview call fails (bad cron, unknown timezone, unsupported cron_version), the error is rethrown with this prefix so the model/user sees that the schedule definition itself — not the create call — was invalid.

Source

Thrown at frontend/src/lib/components/copilot/chat/workspaceTools.ts:352

			if (dropped.length) {
				throw new Error(
					describeDroppedScheduleOptions(dropped)
				)
			}

			toolCallbacks.setToolStatus(toolId, {
				content: `Validating schedule "${requestBody.path}"...`
			})
			try {
				await ScheduleService.previewSchedule({
					requestBody: {
						schedule: requestBody.schedule,
						timezone: requestBody.timezone,
						cron_version: requestBody.cron_version ?? undefined
					}
				})
			} catch (error) {
				throw new Error(`Invalid schedule or timezone: ${formatToolError(error)}`)
			}

			toolCallbacks.setToolStatus(toolId, {
				content: `Creating schedule "${requestBody.path}"...`
			})
			try {
				const result = await ScheduleService.createSchedule({ workspace, requestBody })
				const targetKind = getActionTargetKind(requestBody.is_flow)
				const toolResult = {
					success: true,
					path: requestBody.path,
					target_path: requestBody.script_path,
					target_kind: targetKind,
					backend_result: result
				}
				toolCallbacks.setToolStatus(toolId, {
					content: `Created schedule "${requestBody.path}"`,
					result: toolResult,

View on GitHub (pinned to e474e8803c)

Solutions

  1. Fix the cron expression to a valid standard cron (e.g. */5 * * * *)
  2. Use an exact IANA timezone name like 'America/New_York', or omit timezone
  3. Omit cron_version unless the schema explicitly requires it
  4. Validate locally (e.g. cron-parser) before asking the copilot to create the schedule

Example fix

// before
create_schedule({ schedule: 'every 5 minutes', timezone: 'PST' })
// after
create_schedule({ schedule: '*/5 * * * *', timezone: 'America/Los_Angeles' })
Defensive patterns

Strategy: validation

Validate before calling

import cronParser from 'cron-parser'
try { cronParser.parseExpression(schedule) } catch { throw new Error('Invalid cron') }
if (timezone && !Intl.supportedValuesOf('timeZone').includes(timezone)) throw new Error('Invalid timezone')

Try / catch

try {
  await createSchedule({ schedule, timezone })
} catch (e) {
  if (/Invalid schedule or timezone/.test((e as Error).message)) {
    // correct cron or IANA timezone, then retry once
  } else throw e
}

Prevention

When it happens

Trigger: previewSchedule throws for requestBody.schedule, requestBody.timezone, or cron_version: syntactically invalid cron, non-5/6-field expressions the backend rejects, a timezone string not in the IANA database, or an invalid cron_version value.

Common situations: LLM generates an invalid cron (e.g. 'every 5 minutes' verbatim, or 6-field Quartz-style cron the server doesn't accept); user passes 'CET' or 'PST' instead of 'Europe/Paris' / 'America/Los_Angeles'; wrong cron_version for the backend's cron parser.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/ddae85b0ec0ccf2c. Report an issue: GitHub.