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

  1. Provide a threadId in the create input so the options become valid.
  2. Remove signalType/ifActive/ifIdle/resourceId from the input if you did not intend thread-scoped behavior.
  3. 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

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/8532f1ad87088ea4. Report an issue: GitHub.