{"record":{"id":"1e43f4d336bc307b","repo":"mastra-ai/mastra","slug":"encountered-unknown-role-role-when-converting-v-1e43f4","errorCode":null,"errorMessage":"Encountered unknown role ${role} when converting V5 ModelMessage -> V5 LanguageModelV2Message, input message: ${JSON.stringify(modelMessage, null, 2)}","messagePattern":"Encountered unknown role (.+?) when converting V5 ModelMessage -> V5 LanguageModelV2Message, input message: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/agent/message-list/conversion/to-prompt.ts","lineNumber":306,"sourceCode":"    return {\n      ...modelMessage,\n      content: roleContent[role],\n    };\n  }\n  if (role === `user`) {\n    return {\n      ...modelMessage,\n      content: roleContent[role],\n    };\n  }\n  if (role === `assistant`) {\n    return {\n      ...modelMessage,\n      content: roleContent[role],\n    };\n  }\n\n  throw new Error(\n    `Encountered unknown role ${role} when converting V5 ModelMessage -> V5 LanguageModelV2Message, input message: ${JSON.stringify(modelMessage, null, 2)}`,\n  );\n}\n\n/**\n * Convert tool-result `media` parts in a V2 (AI SDK v5 / spec `v2`) prompt\n * using a caller-provided target content-part shape.\n *\n * Mastra's `toModelOutput` and the vendored AI SDK v5 use `{ type: 'media' }`\n * as the authored multimodal tool-result content type. Newer AI SDK provider\n * specs use different content-part shapes, so callers provide the target\n * conversion for their provider spec.\n */\nfunction convertToolResultContent(\n  prompt: LanguageModelV2Prompt,\n  convertMediaPart: (contentPart: Record<string, unknown>, mediaType: string) => unknown,\n): LanguageModelV2Prompt {\n  return prompt.map(message => {","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent/message-list/conversion/to-prompt.ts#L288-L324","documentation":"aiV5ModelMessageToV2PromptMessage ends with a catch-all throw when the message role is not one of 'system' | 'user' | 'assistant' | 'tool'. Any other role string cannot be mapped to a LanguageModelV2 prompt message, so the raw message is dumped in the error for debugging.","triggerScenarios":"Passing a message with a typo'd or nonstandard role (e.g. 'function', 'developer', 'Assistant', 'human') to MessageList.add() and then generating a prompt with an AI v5 model.","commonSituations":"Porting from other frameworks (LangChain 'human'/'ai' roles, OpenAI 'developer' role); typos in hand-built histories; deserialized DB rows with corrupted role fields.","solutions":["Normalize roles to one of 'system' | 'user' | 'assistant' | 'tool' before adding to MessageList","Map framework-specific roles ('human'->'user', 'ai'->'assistant') during ingestion","Inspect the JSON in the error message to find the offending message and fix its role at the source","Validate input messages in your ingestion layer"],"exampleFix":"// before\n{ role: 'human', content: 'hi' }\n// after\n{ role: 'user', content: 'hi' }","handlingStrategy":"validation","validationCode":"const ROLES = ['system','user','assistant','tool'];\nif (!ROLES.includes(msg.role)) throw new Error(`Unsupported role ${msg.role}`);","typeGuard":"function isKnownRole(r: string): r is 'system'|'user'|'assistant'|'tool' { return ['system','user','assistant','tool'].includes(r); }","tryCatchPattern":"try { messageList.add(msg); } catch (e) { if (e instanceof Error && e.message.includes('Encountered unknown role')) { const normalized = ROLE_MAP[msg.role] ?? 'user'; messageList.add({ ...msg, role: normalized }); } else throw e; }","preventionTips":["Normalize foreign role vocabularies at ingestion","Never trust role strings from external JSON without validation","Keep a role-mapping table for imported frameworks"],"tags":["message-conversion","invalid-role","ai-sdk-v5"],"backgroundTag":"invalid-message-role","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}