{"record":{"id":"4a2cb2ff6b9790d2","repo":"mastra-ai/mastra","slug":"notification-current-id-is-missing-resourceid","errorCode":null,"errorMessage":"Notification ${current.id} is missing resourceId","messagePattern":"Notification (.+?) is missing resourceId","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/notifications/dispatcher.ts","lineNumber":143,"sourceCode":"}\n\nasync function sendNotificationRecord({\n  mastra,\n  storage,\n  record,\n  now,\n  batchThreadState,\n}: {\n  mastra: Mastra;\n  storage: NotificationsStorage;\n  record: NotificationRecord;\n  now: Date;\n  batchThreadState?: NotificationDeliveryThreadState;\n}): Promise<{ record: NotificationRecord; signal: CreatedAgentSignal } | null> {\n  const current = await storage.getNotification({ threadId: record.threadId, id: record.id });\n  if (!current || current.status !== 'pending' || current.deliveredSignalId) return null;\n  if (!current.agentId) throw new Error(`Notification ${current.id} is missing agentId`);\n  if (!current.resourceId) throw new Error(`Notification ${current.id} is missing resourceId`);\n\n  const agent = (await mastra.getAgentById(current.agentId as never)) as NotificationDispatchAgent;\n  const threadState =\n    batchThreadState ??\n    agentThreadStreamRuntime.getThreadState(\n      { resourceId: current.resourceId, threadId: current.threadId },\n      agent.getPubSub?.(),\n    );\n  if (current.priority === 'high' && current.summarySignalId && threadState === 'active') return null;\n\n  const signal = createNotificationSignal({\n    ...current,\n    status: 'delivered',\n    deliveredAt: now,\n    lastDeliveryAttemptAt: now,\n  });\n  const streamOptions = await resolveIfIdleStreamOptions(mastra, agent, { record: current, threadState, now });\n  const target: SendAgentSignalOptions = {","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/notifications/dispatcher.ts#L125-L161","documentation":"sendNotificationRecord requires the stored notification to have a `resourceId`, since it routes signals to the agent keyed by resourceId + threadId and uses resourceId for thread state lookup. This error is thrown when the pending notification record lacks a resourceId.","triggerScenarios":"Delivery of a pending notification whose storage record has an empty/missing resourceId — e.g. the record was created without the resource identifier, or a storage layer/migration stripped it. The dispatcher reads the fresh record via storage.getNotification and throws before calling getThreadState.","commonSituations":"Creating notifications without supplying the resourceId your app tracks users by; custom storage adapters omitting the field on serialization; schema migrations that made resourceId nullable; importing notification data from another system.","solutions":["Re-create the notification via the official API, always passing the resourceId of the owning user/resource.","Backfill resourceId on existing pending rows in your storage for affected records.","Delete or fail-terminate invalid records so the dispatcher can skip them.","Verify your storage adapter preserves resourceId on save/update (add a round-trip test)."],"exampleFix":"// before\nawait createNotification({ agentId: 'my-agent', threadId: 't1', message: 'hi' }); // no resourceId\n// after\nawait createNotification({ agentId: 'my-agent', resourceId: 'user-1', threadId: 't1', message: 'hi' });","handlingStrategy":"validation","validationCode":"if (!notification.resourceId) {\n  throw new TypeError('Cannot create a notification without a resourceId');\n}\nawait createNotification({ ...notification, resourceId: String(notification.resourceId) });","typeGuard":"function hasResourceId(rec: NotificationRecord): rec is NotificationRecord & { resourceId: string } {\n  return typeof rec.resourceId === 'string' && rec.resourceId.length > 0;\n}","tryCatchPattern":"try {\n  await dispatchNotifications(mastra, storage, records, now);\n} catch (err) {\n  if (err instanceof Error && /is missing resourceId/.test(err.message)) {\n    const id = /Notification (.+) is missing resourceId/.exec(err.message)?.[1];\n    logger.error('Notification record missing resourceId, marking failed', { id });\n    await storage.updateNotification({ id, threadId, status: 'failed', lastDeliveryError: err.message });\n  } else {\n    throw err;\n  }\n}","preventionTips":["Make resourceId a required parameter in your notification-creation wrapper.","Check storage schema/migrations to ensure resourceId is NOT NULL for pending records.","Test custom storage adapters for resourceId round-trip fidelity.","Sweep storage for pending records with null resourceId after imports/migrations."],"tags":["notifications","storage","data-integrity","resource-id"],"backgroundTag":"notification-missing-resource-id","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}