mastra-ai/mastra · error · MastraError
SCHEDULES_THREADLESS_OPTIONS
SCHEDULES_THREADLESS_OPTIONS
Error message
schedules.create: ${offenders.join(', ')} require a threadId. What it means
Schedules.create was called with agent-schedule options (signalType, ifActive, ifIdle, resourceId) but without a threadId. These options are thread-scoped and only meaningful for agent schedules, so the library rejects the combination up front with a 400-class user error naming each offending key.
Source
Thrown at packages/core/src/schedules/schedules.ts:300
}
if (input.threadId && !input.resourceId) {
throw new MastraError({
id: 'SCHEDULES_MISSING_RESOURCE_ID',
domain: ErrorDomain.AGENT,
category: ErrorCategory.USER,
details: { status: 400 },
text: 'schedules.create requires `resourceId` when `threadId` is set.',
});
}
if (!input.threadId) {
const offenders: string[] = [];
if (input.signalType !== undefined) offenders.push('signalType');
if (input.ifActive !== undefined) offenders.push('ifActive');
if (input.ifIdle !== undefined) offenders.push('ifIdle');
if (input.resourceId !== undefined) offenders.push('resourceId');
if (offenders.length > 0) {
throw new MastraError({
id: 'SCHEDULES_THREADLESS_OPTIONS',
domain: ErrorDomain.AGENT,
category: ErrorCategory.USER,
details: { status: 400 },
text: `schedules.create: ${offenders.join(', ')} require a threadId.`,
});
}
}
const store = await this.#getStore();
// Make sure the scheduler + agent-schedule worker are running. Boot-time
// detection covers existing rows; imperative creates after
// startWorkers() need to flip the request flag and lazily inject.
await this.#mastra.__ensureScheduleRuntimeReady();
const id =
input.id !== undefined
? normalizeScheduleId(input.id, AGENT_SCHEDULE_PREFIX)View on GitHub (pinned to 75dd419e61)
Solutions
- Provide a threadId in the create input so the options become valid.
- Remove signalType/ifActive/ifIdle/resourceId from the input if you did not intend thread-scoped behavior.
- If you meant a workflow schedule, remove agent-only options entirely (they are meaningless there).
Example fix
// before
await schedules.create({ id: 'daily', cron: '0 9 * * *', ifActive: 'skip' });
// after
await schedules.create({ id: 'daily', cron: '0 9 * * *', threadId: 'thread-1', ifActive: 'skip' }); Defensive patterns
Strategy: validation
Validate before calling
const agentOnlyKeys = ['signalType', 'ifActive', 'ifIdle', 'resourceId'];
const hasAgentOnly = agentOnlyKeys.some(k => input[k] !== undefined);
if (hasAgentOnly && !input.threadId) {
throw new Error('agent-schedule options require a threadId');
}
await schedules.create(input); Type guard
function canCreateAgentSchedule(input: CreateScheduleInput): input is CreateScheduleInput & { threadId: string } {
const hasAgentOnly = ['signalType', 'ifActive', 'ifIdle', 'resourceId'].some(k => (input as any)[k] !== undefined);
return !hasAgentOnly || typeof input.threadId === 'string';
} Prevention
- Always define threadId when creating agent schedules with collision/signal options.
- Keep separate input types for agent vs workflow schedules so invalid keys fail typecheck.
- Centralize schedule creation in one helper that validates the options combination.
When it happens
Trigger: Calling schedules.create() (via createAgentSchedule) where any of input.signalType, input.ifActive, input.ifIdle, or input.resourceId is !== undefined while input.threadId is undefined.
Common situations: Copying a workflow-schedule config into an agent schedule; adding ifActive/ifIdle collision options without wiring the schedule to a memory thread; passing resourceId because of confusion with agent resourceId vs schedule threadId.
Related errors
- AGENT_REQUEST_CONTEXT_VALIDATION_FAILED
- Either message or messages must be provided
- AGENT_LIST_SUSPENDED_RUNS_INVALID_PER_PAGE
- AGENT_LIST_SUSPENDED_RUNS_INVALID_PAGE
- AGENT_SEND_STREAM_RESUME_MISSING_TARGET
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/8532f1ad87088ea4.
Report an issue: GitHub.