mastra-ai/mastra · error · MastraError

PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST

PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST

Error message

Processor ${processor.id} returned a MessageList instance other than the one that was passed in as an argument. New external message list instances are not supported. Use the messageList argument instead.

What it means

Thrown when a processor's processOutputResult returns a brand-new MessageList instance instead of mutating the messageList argument it was given. The runner only accepts the same instance so recorded mutations can be reconciled; returning a foreign MessageList would silently discard the runner's mutation recording. Category USER, domain AGENT, id PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST.

Source

Thrown at packages/core/src/processors/runner.ts:739

          messageList,
          state: processorState.customState,
          result: result ?? defaultResult,
          abort,
          agent: this.agent,
          ...createObservabilityContext({ currentSpan: processorSpan }),
          requestContext,
          retryCount,
          writer,
          sendSignal: createProcessorSendSignal({ messageList, writer }),
        });

        // Stop recording and get mutations for this processor
        const mutations = messageList.stopRecording();

        // Handle the new return type - MessageList or MastraDBMessage[]
        if (processResult instanceof MessageList) {
          if (processResult !== messageList) {
            throw new MastraError({
              category: 'USER',
              domain: 'AGENT',
              id: 'PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST',
              text: `Processor ${processor.id} returned a MessageList instance other than the one that was passed in as an argument. New external message list instances are not supported. Use the messageList argument instead.`,
            });
          }
          if (mutations.length > 0) {
            processableMessages = getProcessableResponseMessages(processResult);
          }
        } else {
          if (processResult) {
            const deletedIds = idsBeforeProcessing.filter(
              (i: string) => !processResult.some((m: MastraDBMessage) => m.id === i),
            );
            if (deletedIds.length) {
              messageList.removeByIds(deletedIds);
            }
            processableMessages = processResult || [];

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Mutate the passed-in messageList in place (its add/remove/update APIs) and return it (or return nothing/arrays per the supported signatures).
  2. If you need filtering, remove messages from the existing messageList rather than building a new one.
  3. If you truly need a fresh list, do it outside the processor or restructure so the runner-owned list stays canonical.

Example fix

// before
processOutputResult: async ({ messageList }) => {
  const filtered = new MessageList();
  for (const m of messageList.get.all()) if (!isBlocked(m)) filtered.add(m);
  return filtered;
}
// after
processOutputResult: async ({ messageList }) => {
  for (const m of messageList.get.all()) if (isBlocked(m)) messageList.remove(m);
  return messageList;
}
Defensive patterns

Strategy: validation

Validate before calling

// Enforce in code review / wrapper:
function assertSameMessageList(returned: unknown, expected: MessageList) {
  if (returned instanceof MessageList && returned !== expected)
    throw new Error('Processor must return the SAME messageList instance it received');
}

Type guard

function returnsForeignList<T extends MessageList>(ret: T, arg: MessageList): boolean {
  return ret instanceof MessageList && ret !== arg;
}

Try / catch

try {
  await agent.generate(input);
} catch (e) {
  if (e instanceof MastraError && e.id === 'PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST') {
    const processorId = /Processor (.+?) returned/.exec(e.message)?.[1];
    console.error(`Fix processor ${processorId}: mutate the given messageList, do not return a new one`);
  } else throw e;
}

Prevention

When it happens

Trigger: Inside processOutputResult, code like `return new MessageList().add(messages)` or returning a MessageList obtained from elsewhere (memory, another agent) instead of the passed-in messageList.

Common situations: Migrating processors from the old array-return style to MessageList; constructing a filtered copy of messages and returning it; wrapping the argument list in a fresh MessageList to 're-parse' it.

Related errors


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