mastra-ai/mastra · error

Missing message source for message ${message}

Error message

Missing message source for message ${message}

What it means

MessageStateManager.addToSource buckets each message into a source set ('memory', 'input', 'context', ...). If a message arrives with a source value outside the known switch cases, it throws 'Missing message source for message <message>'. This is an internal invariant violation indicating the message carried an unrecognized/undefined source tag.

Source

Thrown at packages/core/src/agent/message-list/state/MessageStateManager.ts:66

        }
        this.newResponseMessages.add(message);
        this.newResponseMessagesPersisted.add(message);
        // Handle case where a client-side tool response was added as user input
        if (this.newUserMessages.has(message)) {
          this.newUserMessages.delete(message);
        }
        break;
      case 'input':
      case 'user': // deprecated alias for input
        this.newUserMessages.add(message);
        this.newUserMessagesPersisted.add(message);
        break;
      case 'context':
        this.userContextMessages.add(message);
        this.userContextMessagesPersisted.add(message);
        break;
      default:
        throw new Error(`Missing message source for message ${message}`);
    }
  }

  /**
   * Check if a message belongs to the memory source
   */
  isMemoryMessage(message: MastraDBMessage): boolean {
    return this.memoryMessages.has(message);
  }

  /**
   * Check if a message belongs to the input source
   */
  isUserMessage(message: MastraDBMessage): boolean {
    return this.newUserMessages.has(message);
  }

  /**

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Always add messages through the public MessageList.add APIs with an explicit messageSource ('memory', 'input', 'context', or 'response').
  2. Check the message printed in the error for a missing/misspelled source field and fix the producer.
  3. Align package versions (@mastra/core and dependent packages) so MessageSource unions match.
  4. If migrating stored messages, backfill the source metadata during deserialization.

Example fix

// before
stateManager.addToSource(msg, undefined as any);
// after
stateManager.addToSource(msg, 'input');
Defensive patterns

Strategy: type-guard

Validate before calling

const VALID_SOURCES = ['memory', 'input', 'context', 'response'] as const;
function assertMessageSource(src: string | undefined) {
  if (!src || !(VALID_SOURCES as readonly string[]).includes(src)) {
    throw new Error(`Message source must be one of ${VALID_SOURCES.join('|')}, got: ${src}`);
  }
}

Type guard

function hasMessageSource(m: unknown): m is { source: 'memory' | 'input' | 'context' | 'response' } {
  return typeof m === 'object' && m !== null &&
    ['memory', 'input', 'context', 'response'].includes((m as any).source);
}

Try / catch

try {
  messageList.add(msg, source);
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Missing message source for message')) {
    console.error('Message added without a recognized source; defaulting to input');
    messageList.add(msg, 'input');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling MessageStateManager methods (via updateMessageMetadataByToolCallId, mergeToolResultIntoPart, stepStart, markResponseMessageBoundary, etc.) with a message whose source is undefined or an unsupported string — typically from a caller that constructed a MessageList entry without tagging its origin.

Common situations: Custom code adding messages to MessageList via internal APIs without passing messageSource; storage layers deserializing messages that lost their source metadata; version mismatches between packages that changed the MessageSource union.

Related errors


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