windmill-labs/windmill · error

describeDroppedScheduleOptions(dropped)

Error message

describeDroppedScheduleOptions(dropped)

What it means

After merging `advanced` options with top-level args for create_schedule, droppedOptionKeys detects keys that were swallowed (not represented in the parsed NewSchedule body). If any option the caller supplied would be silently dropped, describeDroppedScheduleOptions produces this error instead of creating a half-configured schedule. It protects against schema/definition drift where an advanced option is passed under the wrong level or name.

Source

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

		try {
			const { advanced, ...rest } = (args ?? {}) as Record<string, unknown>
			// `advanced` carries what the definition does not list: a named argument outranks
			// a duplicate inside the bag, and the runnable target outranks both. The whole
			// merged object is checked for stripped keys, not just the bag: an advanced option
			// passed at the top level instead would otherwise be dropped without a word.
			const merged = {
				...((advanced as Record<string, unknown>) ?? {}),
				...rest,
				...getWorkspaceMutationTargetFields(helpers)
			}
			const requestBody = parseWithExplicitErrors(
				scheduleRequestSchema as z.ZodType<NewSchedule>,
				merged,
				'Schedule'
			)
			const dropped = droppedOptionKeys(merged, requestBody)
			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)}`)
			}

View on GitHub (pinned to e474e8803c)

Solutions

  1. Call get_schedule_schema and move the listed option into the `advanced` object with its exact name
  2. Remove the unrecognized/unsupported option and retry with only schema-listed fields
  3. Update the frontend schedule schema if a legitimately new server option is missing

Example fix

// before
create_schedule({ path: 's/x', schedule: '* * * * *', retry: { retries: 3 } })
// after
create_schedule({ path: 's/x', schedule: '* * * * *', advanced: { retry: { retries: 3 } } })
Defensive patterns

Strategy: validation

Validate before calling

const known = new Set(Object.keys(scheduleRequestSchema.shape))
const supplied = Object.keys(merged)
const bad = supplied.filter((k) => !known.has(k))
if (bad.length) throw new Error(`Unsupported schedule options: ${bad.join(', ')}`)

Try / catch

try {
  await createSchedule(args)
} catch (e) {
  if (/dropped/i.test((e as Error).message)) {
    const schema = await getScheduleSchema()
    return createSchedule(withAdvancedFromSchema(schema, args))
  }
  throw e
}

Prevention

When it happens

Trigger: The agent passes schedule options (e.g. retry, pause, tags, error handler) either at the top level instead of inside `advanced`, or under a misspelled/unknown key inside `advanced`, such that after zod parsing the key does not survive into the request body.

Common situations: Model invents an option name not in the schedule schema; an option from get_schedule_schema is placed at the top level next to `advanced` and outranked/duplicated; newer server-side schedule fields not yet in the frontend schema.

Related errors


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