{"record":{"id":"bd24975e61bcc473","repo":"mastra-ai/mastra","slug":"processor-returned-external-message-list","errorCode":"PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST","errorMessage":"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.","messagePattern":"Processor (.+?) 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\\.","errorType":"error_code","errorClass":"MastraError","httpStatus":null,"severity":"error","filePath":"packages/core/src/processors/runner.ts","lineNumber":739,"sourceCode":"          messageList,\n          state: processorState.customState,\n          result: result ?? defaultResult,\n          abort,\n          agent: this.agent,\n          ...createObservabilityContext({ currentSpan: processorSpan }),\n          requestContext,\n          retryCount,\n          writer,\n          sendSignal: createProcessorSendSignal({ messageList, writer }),\n        });\n\n        // Stop recording and get mutations for this processor\n        const mutations = messageList.stopRecording();\n\n        // Handle the new return type - MessageList or MastraDBMessage[]\n        if (processResult instanceof MessageList) {\n          if (processResult !== messageList) {\n            throw new MastraError({\n              category: 'USER',\n              domain: 'AGENT',\n              id: 'PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST',\n              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.`,\n            });\n          }\n          if (mutations.length > 0) {\n            processableMessages = getProcessableResponseMessages(processResult);\n          }\n        } else {\n          if (processResult) {\n            const deletedIds = idsBeforeProcessing.filter(\n              (i: string) => !processResult.some((m: MastraDBMessage) => m.id === i),\n            );\n            if (deletedIds.length) {\n              messageList.removeByIds(deletedIds);\n            }\n            processableMessages = processResult || [];","sourceCodeStart":721,"sourceCodeEnd":757,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/processors/runner.ts#L721-L757","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Mutate the passed-in messageList in place (its add/remove/update APIs) and return it (or return nothing/arrays per the supported signatures).","If you need filtering, remove messages from the existing messageList rather than building a new one.","If you truly need a fresh list, do it outside the processor or restructure so the runner-owned list stays canonical."],"exampleFix":"// before\nprocessOutputResult: async ({ messageList }) => {\n  const filtered = new MessageList();\n  for (const m of messageList.get.all()) if (!isBlocked(m)) filtered.add(m);\n  return filtered;\n}\n// after\nprocessOutputResult: async ({ messageList }) => {\n  for (const m of messageList.get.all()) if (isBlocked(m)) messageList.remove(m);\n  return messageList;\n}","handlingStrategy":"validation","validationCode":"// Enforce in code review / wrapper:\nfunction assertSameMessageList(returned: unknown, expected: MessageList) {\n  if (returned instanceof MessageList && returned !== expected)\n    throw new Error('Processor must return the SAME messageList instance it received');\n}","typeGuard":"function returnsForeignList<T extends MessageList>(ret: T, arg: MessageList): boolean {\n  return ret instanceof MessageList && ret !== arg;\n}","tryCatchPattern":"try {\n  await agent.generate(input);\n} catch (e) {\n  if (e instanceof MastraError && e.id === 'PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST') {\n    const processorId = /Processor (.+?) returned/.exec(e.message)?.[1];\n    console.error(`Fix processor ${processorId}: mutate the given messageList, do not return a new one`);\n  } else throw e;\n}","preventionTips":["Never construct `new MessageList()` inside processOutputResult/processInput","Use the messageList argument's mutation APIs (add/remove/update/clear)","When migrating from array-return processors, return the same list or plain arrays, not new lists","Add a unit test asserting the processor returns the identical instance"],"tags":["agent","processors","messagelist","api-misuse"],"backgroundTag":"processor-foreign-messagelist","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}