{"record":{"id":"ead66c89dbf5fa62","repo":"windmill-labs/windmill","slug":"describedroppedscheduleoptions-dropped","errorCode":null,"errorMessage":"describeDroppedScheduleOptions(dropped)","messagePattern":"describeDroppedScheduleOptions\\(dropped\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/global/core.ts","lineNumber":3555,"sourceCode":"\t\t\twriteScheduleToolSchema,\n\t\t\t'write_schedule',\n\t\t\t'Create or overwrite a draft schedule.',\n\t\t\t{ strict: false }\n\t\t),\n\t\tshowDetails: true,\n\t\tstreamArguments: true,\n\t\tshowFade: true,\n\t\tfn: async (ctx) => {\n\t\t\tconst { advanced, ...rest } = (ctx.args ?? {}) as Record<string, unknown>\n\t\t\t// `advanced` carries what the definition does not list, so a named argument\n\t\t\t// outranks a duplicate of the same key inside the bag. The whole merged object\n\t\t\t// is checked for stripped keys, not just the bag: an advanced option passed at\n\t\t\t// the top level instead would otherwise be dropped without a word.\n\t\t\tconst merged = { ...((advanced as Record<string, unknown>) ?? {}), ...rest }\n\t\t\tconst parsed = writeScheduleSchema.parse(merged)\n\t\t\tconst dropped = droppedOptionKeys(merged, parsed)\n\t\t\tif (dropped.length) {\n\t\t\t\tthrow new Error(describeDroppedScheduleOptions(dropped))\n\t\t\t}\n\t\t\treturn writeScheduleDraft(parsed, ctx)\n\t\t}\n\t},\n\t{\n\t\tdef: createToolDef(\n\t\t\twriteTriggerSchema,\n\t\t\t'write_trigger',\n\t\t\t'Create or overwrite a draft trigger.',\n\t\t\t{ strict: false }\n\t\t),\n\t\tshowDetails: true,\n\t\tstreamArguments: true,\n\t\tshowFade: true,\n\t\tfn: async (ctx) => {\n\t\t\tconst parsed = writeTriggerSchema.parse(ctx.args)\n\t\t\t// writeTriggerDraft dispatches on `kind`, so a config belonging to another kind\n\t\t\t// has to be rejected here rather than reaching the API as a corrupt draft. The","sourceCodeStart":3537,"sourceCodeEnd":3573,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/global/core.ts#L3537-L3573","documentation":"When writing a schedule draft, unknown or misplaced option keys are detected by comparing the merged input against the parsed schema output. If any keys would be silently dropped, this error is thrown listing them, instead of letting them vanish unnoticed.","triggerScenarios":"A write_schedule tool call includes keys not part of writeScheduleSchema (e.g. an advanced option placed at the top level of the args bag instead of inside the advanced object), so droppedOptionKeys(merged, parsed) returns a non-empty list.","commonSituations":"The model nests schedule options in the wrong place, uses an out-of-schema field name, or passes a deprecated option key.","solutions":["Move advanced options into the 'advanced' object instead of the top level","Remove or correct keys that are not part of writeScheduleSchema","Call the schedule schema/get tool first to see the accepted fields, then retry"],"exampleFix":"// before\nwriteSchedule({ path: 'p/sched', schedule: 'x', timezone: 'UTC', summary: 'oops' })\n// after\nwriteSchedule({ path: 'p/sched', schedule: 'x', timezone: 'UTC' })","handlingStrategy":"validation","validationCode":"const merged = { ...advanced, ...rest };\nconst parsed = writeScheduleSchema.safeParse(merged);\nif (!parsed.success) fixKeysBeforeWriting();","typeGuard":"function isKnownScheduleKey(k) { return k in writeScheduleSchema.shape; }","tryCatchPattern":"try { writeSchedule(args) } catch (e) { if (e.message.startsWith('Dropped')) moveKeysIntoAdvanced(e); }","preventionTips":["Nest advanced options inside the advanced object","Validate keys against writeScheduleSchema before writing"],"tags":["ai-copilot","schema-validation","schedule"],"backgroundTag":"schema-validation-failed","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}