mastra-ai/mastra · error

Notification ${current.id} is missing resourceId

Error message

Notification ${current.id} is missing resourceId

What it means

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.

Source

Thrown at packages/core/src/notifications/dispatcher.ts:143

}

async function sendNotificationRecord({
  mastra,
  storage,
  record,
  now,
  batchThreadState,
}: {
  mastra: Mastra;
  storage: NotificationsStorage;
  record: NotificationRecord;
  now: Date;
  batchThreadState?: NotificationDeliveryThreadState;
}): Promise<{ record: NotificationRecord; signal: CreatedAgentSignal } | null> {
  const current = await storage.getNotification({ threadId: record.threadId, id: record.id });
  if (!current || current.status !== 'pending' || current.deliveredSignalId) return null;
  if (!current.agentId) throw new Error(`Notification ${current.id} is missing agentId`);
  if (!current.resourceId) throw new Error(`Notification ${current.id} is missing resourceId`);

  const agent = (await mastra.getAgentById(current.agentId as never)) as NotificationDispatchAgent;
  const threadState =
    batchThreadState ??
    agentThreadStreamRuntime.getThreadState(
      { resourceId: current.resourceId, threadId: current.threadId },
      agent.getPubSub?.(),
    );
  if (current.priority === 'high' && current.summarySignalId && threadState === 'active') return null;

  const signal = createNotificationSignal({
    ...current,
    status: 'delivered',
    deliveredAt: now,
    lastDeliveryAttemptAt: now,
  });
  const streamOptions = await resolveIfIdleStreamOptions(mastra, agent, { record: current, threadState, now });
  const target: SendAgentSignalOptions = {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Re-create the notification via the official API, always passing the resourceId of the owning user/resource.
  2. Backfill resourceId on existing pending rows in your storage for affected records.
  3. Delete or fail-terminate invalid records so the dispatcher can skip them.
  4. Verify your storage adapter preserves resourceId on save/update (add a round-trip test).

Example fix

// before
await createNotification({ agentId: 'my-agent', threadId: 't1', message: 'hi' }); // no resourceId
// after
await createNotification({ agentId: 'my-agent', resourceId: 'user-1', threadId: 't1', message: 'hi' });
Defensive patterns

Strategy: validation

Validate before calling

if (!notification.resourceId) {
  throw new TypeError('Cannot create a notification without a resourceId');
}
await createNotification({ ...notification, resourceId: String(notification.resourceId) });

Type guard

function hasResourceId(rec: NotificationRecord): rec is NotificationRecord & { resourceId: string } {
  return typeof rec.resourceId === 'string' && rec.resourceId.length > 0;
}

Try / catch

try {
  await dispatchNotifications(mastra, storage, records, now);
} catch (err) {
  if (err instanceof Error && /is missing resourceId/.test(err.message)) {
    const id = /Notification (.+) is missing resourceId/.exec(err.message)?.[1];
    logger.error('Notification record missing resourceId, marking failed', { id });
    await storage.updateNotification({ id, threadId, status: 'failed', lastDeliveryError: err.message });
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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