mastra-ai/mastra · error · MastraError
SCHEDULES_AMBIGUOUS_MODE
SCHEDULES_AMBIGUOUS_MODE
Error message
Schedule${where}: set exactly one execution mode — remove either 'prompt' or 'handler'. What it means
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.
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.
Example fix
// before
defineSchedule({
cron: '0 9 * * *',
prompt: 'Check system health.',
handler: async ({ agent }) => { /* ... */ },
});
// after
defineSchedule({
cron: '0 9 * * *',
handler: async ({ agent }) => { /* ... */ },
}); Defensive patterns
Strategy: validation
Validate before calling
function hasExecMode(def) {
const hasPrompt = typeof def?.prompt === 'string' && def.prompt.trim() !== '';
const hasHandler = typeof def?.handler === 'function';
return hasPrompt !== hasHandler; // exactly one
}
if (!hasExecMode(mySchedule)) throw new Error('Set exactly one of prompt or handler'); Type guard
function hasExactlyOneMode(def: { prompt?: string; handler?: unknown }): boolean {
const hasPrompt = typeof def.prompt === 'string' && def.prompt.trim() !== '';
const hasHandler = typeof def.handler === 'function';
return hasPrompt !== hasHandler;
} Try / catch
try {
const schedule = defineSchedule(def);
} catch (e) {
if (e instanceof MastraError && e.id === 'SCHEDULES_AMBIGUOUS_MODE') {
// drop one of prompt/handler and retry, or surface a config error
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- SCHEDULES_MISSING_MODE
- SCHEDULES_INVALID_CRON
- SCHEDULES_INVALID_DEFINITION
- SCHEDULES_INVALID_ID
- SCHEDULES_INVALID_SIGNAL_TYPE
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/08c1cea7721e5448.
Report an issue: GitHub.
Appendix: source
Thrown at packages/core/src/schedules/define.ts:168
*/
export function assertValidScheduleDefinition(definition: AgentScheduleDefinition<any>, label?: string): void {
const where = label ? ` (${label})` : '';
if (!definition || typeof definition !== 'object') {
throw new MastraError({
id: 'SCHEDULES_INVALID_DEFINITION',
domain: ErrorDomain.AGENT,
category: ErrorCategory.USER,
details: { label: label ?? '' },
text: `Schedule${where}: expected a schedule definition object, received ${definition === null ? 'null' : typeof definition}.`,
});
}
const hasPrompt = typeof definition.prompt === 'string' && definition.prompt.trim() !== '';
const hasHandler = typeof definition.handler === 'function';
if (hasPrompt && hasHandler) {
throw new MastraError({
id: 'SCHEDULES_AMBIGUOUS_MODE',
domain: ErrorDomain.AGENT,
category: ErrorCategory.USER,
details: { label: label ?? '' },
text: `Schedule${where}: set exactly one execution mode — remove either 'prompt' or 'handler'.`,
});
}
if (!hasPrompt && !hasHandler) {
throw new MastraError({
id: 'SCHEDULES_MISSING_MODE',
domain: ErrorDomain.AGENT,
category: ErrorCategory.USER,
details: { label: label ?? '' },
text: `Schedule${where}: set exactly one execution mode — provide a non-empty 'prompt' or a 'handler' function.`,
});
}
View on GitHub (pinned to 75dd419e61)