{"record":{"id":"b0d7f74728118da0","repo":"mastra-ai/mastra","slug":"schedules-missing-resource-id","errorCode":"SCHEDULES_MISSING_RESOURCE_ID","errorMessage":"Schedule${where}: 'resourceId' is required when 'threadId' is set.","messagePattern":"Schedule(.+?): 'resourceId' is required when 'threadId' is set\\.","errorType":"error_code","errorClass":"MastraError","httpStatus":null,"severity":"error","filePath":"packages/core/src/schedules/define.ts","lineNumber":226,"sourceCode":"      domain: ErrorDomain.AGENT,\n      category: ErrorCategory.USER,\n      details: { label: label ?? '', signalType: String(definition.signalType) },\n      text: `Schedule${where}: unknown signalType \"${definition.signalType}\". Expected one of: ${SCHEDULE_SIGNAL_TYPES.join(', ')}.`,\n    });\n  }\n\n  if (definition.status !== undefined && !SCHEDULE_STATUSES.includes(definition.status)) {\n    throw new MastraError({\n      id: 'SCHEDULES_INVALID_STATUS',\n      domain: ErrorDomain.AGENT,\n      category: ErrorCategory.USER,\n      details: { label: label ?? '', status: String(definition.status) },\n      text: `Schedule${where}: unknown status \"${definition.status}\". Expected one of: ${SCHEDULE_STATUSES.join(', ')}.`,\n    });\n  }\n\n  if (definition.threadId && !definition.resourceId) {\n    throw new MastraError({\n      id: 'SCHEDULES_MISSING_RESOURCE_ID',\n      domain: ErrorDomain.AGENT,\n      category: ErrorCategory.USER,\n      details: { label: label ?? '' },\n      text: `Schedule${where}: 'resourceId' is required when 'threadId' is set.`,\n    });\n  }\n}\n\n/**\n * Encode one component of a row id so it cannot contain the `__` delimiter.\n *\n * `encodeURIComponent` leaves `_` untouched, so escaping it explicitly is what\n * actually makes the delimiter unambiguous — otherwise an agent named `a__b`\n * and one named `a` with a key starting `_b` would produce the same row id.\n * `decodeURIComponent` reverses `%5F` for free.\n */\nfunction encodeRowIdPart(value: string): string {","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/schedules/define.ts#L208-L244","documentation":"Mastra schedules support attaching a memory thread (`threadId`) to an agent schedule, but a thread can only be resolved when its owning resource is also given via `resourceId`. When a schedule definition sets `threadId` without `resourceId`, `assertValidScheduleDefinition` in packages/core/src/schedules/define.ts:226 throws SCHEDULES_MISSING_RESOURCE_ID so the invalid pair is rejected before it is persisted. This is a user-category validation error, raised at definition time (including for Markdown-defined schedules) rather than at fire time.","triggerScenarios":"Calling `mastra.getSchedule(...)`/`defineSchedule` (or `resolveSchedules`) with a definition object containing a truthy `threadId` and an undefined/empty `resourceId`, e.g. `{ agentId, prompt, cron: '0 9 * * *', threadId: 'thread_123' }` with no `resourceId`.","commonSituations":"Copy-pasting a schedule config that mentions threadId but omitting resourceId; wiring memory threads to scheduled agent prompts and assuming threadId alone identifies the thread; partially migrating configs where resourceId was added later; Markdown/YAML schedule files that only got the threadId field filled in.","solutions":["Add the matching `resourceId` (the resource that owns the thread) to the schedule definition alongside `threadId`.","If the schedule should not use memory threads, remove `threadId` instead of adding a resourceId.","Re-run/reload after fixing; for Markdown-defined schedules, correct the frontmatter/definition and reload the schedules."],"exampleFix":"// before\nmastra.defineSchedule({\n  id: 'daily-digest',\n  agentId: 'assistant',\n  prompt: 'Summarize the thread',\n  cron: '0 9 * * *',\n  threadId: 'thread_123',\n});\n\n// after\nmastra.defineSchedule({\n  id: 'daily-digest',\n  agentId: 'assistant',\n  prompt: 'Summarize the thread',\n  cron: '0 9 * * *',\n  threadId: 'thread_123',\n  resourceId: 'user_42',\n});","handlingStrategy":"validation","validationCode":"function canDefineSchedule(def) {\n  return !(def.threadId && !def.resourceId);\n}\nif (!canDefineSchedule(def)) {\n  throw new Error('resourceId is required when threadId is set');\n}","typeGuard":"function hasResourceForThread(def): def is typeof def & { resourceId: string } {\n  return !def.threadId || typeof def.resourceId === 'string' && def.resourceId.length > 0;\n}","tryCatchPattern":"import { MastraError } from '@mastra/core/error';\ntry {\n  mastra.defineSchedule(def);\n} catch (e) {\n  if (e instanceof MastraError && e.id === 'SCHEDULES_MISSING_RESOURCE_ID') {\n    console.error(`Schedule ${e.details?.label}: add resourceId or remove threadId`);\n  } else throw e;\n}","preventionTips":["Always pair threadId with resourceId in schedule definitions.","Run definition validation (assertValidScheduleDefinition) early in tests.","Lint Markdown/YAML schedule files for threadId-without-resourceId."],"tags":["schedules","validation","config","user-error"],"backgroundTag":"missing-required-field","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}