{"record":{"id":"08c1cea7721e5448","repo":"mastra-ai/mastra","slug":"schedules-ambiguous-mode","errorCode":"SCHEDULES_AMBIGUOUS_MODE","errorMessage":"Schedule${where}: set exactly one execution mode — remove either 'prompt' or 'handler'.","messagePattern":"Schedule(.+?): set exactly one execution mode — remove either 'prompt' or 'handler'\\.","errorType":"error_code","errorClass":"MastraError","httpStatus":null,"severity":"error","filePath":"packages/core/src/schedules/define.ts","lineNumber":168,"sourceCode":" */\nexport function assertValidScheduleDefinition(definition: AgentScheduleDefinition<any>, label?: string): void {\n  const where = label ? ` (${label})` : '';\n\n  if (!definition || typeof definition !== 'object') {\n    throw new MastraError({\n      id: 'SCHEDULES_INVALID_DEFINITION',\n      domain: ErrorDomain.AGENT,\n      category: ErrorCategory.USER,\n      details: { label: label ?? '' },\n      text: `Schedule${where}: expected a schedule definition object, received ${definition === null ? 'null' : typeof definition}.`,\n    });\n  }\n\n  const hasPrompt = typeof definition.prompt === 'string' && definition.prompt.trim() !== '';\n  const hasHandler = typeof definition.handler === 'function';\n\n  if (hasPrompt && hasHandler) {\n    throw new MastraError({\n      id: 'SCHEDULES_AMBIGUOUS_MODE',\n      domain: ErrorDomain.AGENT,\n      category: ErrorCategory.USER,\n      details: { label: label ?? '' },\n      text: `Schedule${where}: set exactly one execution mode — remove either 'prompt' or 'handler'.`,\n    });\n  }\n\n  if (!hasPrompt && !hasHandler) {\n    throw new MastraError({\n      id: 'SCHEDULES_MISSING_MODE',\n      domain: ErrorDomain.AGENT,\n      category: ErrorCategory.USER,\n      details: { label: label ?? '' },\n      text: `Schedule${where}: set exactly one execution mode — provide a non-empty 'prompt' or a 'handler' function.`,\n    });\n  }\n","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/schedules/define.ts#L150-L186","documentation":"A schedule definition passed both a 'prompt' and a 'handler', which are mutually exclusive execution modes: a schedule runs either by sending a prompt to an agent or by calling a handler function, never both. Mastra throws this at definition time (via defineSchedule or file-based assembly through assertValidScheduleDefinition) so the ambiguity is caught before the schedule is stored or fired. The error text includes the schedule label when one is known.","triggerScenarios":"Calling defineSchedule({cron, prompt, handler}) with both a non-empty prompt string and a handler function; passing an assembled/markdown schedule object to resolveSchedules/assertValidScheduleDefinition where both fields ended up set (e.g. merging defaults with a user definition).","commonSituations":"Copying an example that used 'prompt' into code that already had a 'handler'; a config merge spreading base defaults containing 'prompt' over an object that defines 'handler'; refactoring from prompt-mode to handler-mode and leaving the old prompt field in place; TypeScript not catching it because markdown/file-based schedules bypass type checking.","solutions":["Remove the 'prompt' field if you want the schedule to run the handler function.","Remove the 'handler' field (set it to undefined) if you want the schedule to send the prompt to the agent.","If both came from a merge/defaults spread, explicitly delete the unwanted key (e.g. `delete merged.prompt`) before calling defineSchedule.","Re-run or rebuild so assertValidScheduleDefinition passes and the schedule registers."],"exampleFix":"// before\ndefineSchedule({\n  cron: '0 9 * * *',\n  prompt: 'Check system health.',\n  handler: async ({ agent }) => { /* ... */ },\n});\n// after\ndefineSchedule({\n  cron: '0 9 * * *',\n  handler: async ({ agent }) => { /* ... */ },\n});","handlingStrategy":"validation","validationCode":"function hasExecMode(def) {\n  const hasPrompt = typeof def?.prompt === 'string' && def.prompt.trim() !== '';\n  const hasHandler = typeof def?.handler === 'function';\n  return hasPrompt !== hasHandler; // exactly one\n}\nif (!hasExecMode(mySchedule)) throw new Error('Set exactly one of prompt or handler');","typeGuard":"function hasExactlyOneMode(def: { prompt?: string; handler?: unknown }): boolean {\n  const hasPrompt = typeof def.prompt === 'string' && def.prompt.trim() !== '';\n  const hasHandler = typeof def.handler === 'function';\n  return hasPrompt !== hasHandler;\n}","tryCatchPattern":"try {\n  const schedule = defineSchedule(def);\n} catch (e) {\n  if (e instanceof MastraError && e.id === 'SCHEDULES_AMBIGUOUS_MODE') {\n    // drop one of prompt/handler and retry, or surface a config error\n  } else throw e;\n}","preventionTips":["Decide on one execution mode per schedule and never set both fields in shared defaults.","When merging config objects, explicitly delete the excluded key instead of spreading both sources.","Use defineSchedule() at author time so TypeScript and runtime validation catch the conflict immediately.","Add a lint/test that scans schedule definitions for both fields before deploy."],"tags":["schedules","configuration","validation","user-error"],"backgroundTag":"ambiguous-schedule-execution-mode","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}