{"record":{"id":"dde57dacfa0d228c","repo":"mastra-ai/mastra","slug":"encountered-unknown-role-role-when-converting-v","errorCode":null,"errorMessage":"Encountered unknown role ${role} when converting V4 CoreMessage -> V4 LanguageModelV1Prompt, input message: ${JSON.stringify(coreMessage, null, 2)}","messagePattern":"Encountered unknown role (.+?) when converting V4 CoreMessage -> V4 LanguageModelV1Prompt, input message: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/agent/message-list/conversion/to-prompt.ts","lineNumber":170,"sourceCode":"    return {\n      ...coreMessage,\n      content: roleContent[role],\n    };\n  }\n  if (role === `user`) {\n    return {\n      ...coreMessage,\n      content: roleContent[role],\n    };\n  }\n  if (role === `assistant`) {\n    return {\n      ...coreMessage,\n      content: roleContent[role],\n    };\n  }\n\n  throw new Error(\n    `Encountered unknown role ${role} when converting V4 CoreMessage -> V4 LanguageModelV1Prompt, input message: ${JSON.stringify(coreMessage, null, 2)}`,\n  );\n}\n\n/**\n * Convert an AI SDK V5 ModelMessage to a V2 LanguageModel prompt message.\n * Used for creating LLM prompt messages without AI SDK streamText/generateText.\n */\nexport function aiV5ModelMessageToV2PromptMessage(modelMessage: AIV5Type.ModelMessage): AIV5LanguageModelV2Message {\n  if (modelMessage.role === `system`) {\n    return modelMessage;\n  }\n\n  if (typeof modelMessage.content === `string` && (modelMessage.role === `assistant` || modelMessage.role === `user`)) {\n    return {\n      role: modelMessage.role,\n      content: [{ type: 'text', text: modelMessage.content }],\n      providerOptions: modelMessage.providerOptions,","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent/message-list/conversion/to-prompt.ts#L152-L188","documentation":"At the end of aiV4CoreMessageToV1PromptMessage (to-prompt.ts:170), after all content parts are processed, the role must be one of 'system' | 'user' | 'assistant' | 'tool'. Any other role value falls through every branch and throws with the full input message JSON. Since TypeScript types restrict roles, this usually indicates a runtime value that bypassed the types (any-cast, JSON from storage, wrong SDK version).","triggerScenarios":"Passing a CoreMessage whose role is a non-standard string (e.g. 'function', 'developer', 'model', or undefined after an any-cast) into the V4 prompt conversion path (directly or via MessageList.toPrompt).","commonSituations":"Migrating from OpenAI-style roles ('function'/'developer') or other SDKs ('model' in Gemini/Anthropic style) without remapping; deserialized messages with corrupted role fields; mixing AI SDK v3-era message objects into a v4 pipeline.","solutions":["Remap non-standard roles to the four supported ones: 'function'->'tool' (with tool-result parts), 'developer'/'model'->'assistant' or 'system'.","Validate message roles at your system boundary and reject/normalize unknown values before adding to memory.","Check for any-casts (`as CoreMessage`) hiding bad role values; let the types do their job."],"exampleFix":"// before\nmessages.push({ role: 'model', content: 'hi' } as any)\n// after\nmessages.push({ role: 'assistant', content: 'hi' })","handlingStrategy":"type-guard","validationCode":"const VALID_ROLES = ['system', 'user', 'assistant', 'tool'] as const;\nfunction assertValidRoles(messages: Array<{ role: string }>) {\n  for (const m of messages) {\n    if (!VALID_ROLES.includes(m.role as any))\n      throw new Error(`Role \"${m.role}\" not supported; remap to one of ${VALID_ROLES.join(', ')}`);\n  }\n}","typeGuard":"type PromptRole = 'system' | 'user' | 'assistant' | 'tool';\nfunction hasPromptRole(m: unknown): m is { role: PromptRole } {\n  return typeof m === 'object' && m !== null &&\n    ['system', 'user', 'assistant', 'tool'].includes((m as any).role);\n}","tryCatchPattern":"try {\n  const prompt = messageList.toPrompt();\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Encountered unknown role')) {\n    const role = /unknown role (\\S+)/.exec(e.message)?.[1];\n    console.error(`Remap non-standard role \"${role}\" to system/user/assistant/tool`);\n  } else throw e;\n}","preventionTips":["Remap foreign role vocabularies ('function', 'developer', 'model') at ingestion","Avoid `as CoreMessage` any-casts that hide invalid role values","Validate roles of anything loaded from storage or external APIs before prompt building"],"tags":["message-conversion","ai-sdk-v4","roles","prompt"],"backgroundTag":"invalid-message-role-content","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}