{"record":{"id":"44d48cabe48431d9","repo":"PrefectHQ/fastmcp","slug":"invalid-message-role-message-role","errorCode":null,"errorMessage":"Invalid message role: {message.role}","messagePattern":"Invalid message role: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py","lineNumber":297,"sourceCode":"    \"\"\"Convert MCP messages to Google GenAI content.\"\"\"\n    google_messages: list[Content] = []\n\n    for message in messages:\n        content = message.content\n\n        # Handle list content (tool calls + results)\n        if isinstance(content, list):\n            parts: list[Part] = [\n                _sampling_content_to_google_genai_part(item) for item in content\n            ]\n\n            if message.role == \"user\":\n                google_messages.append(UserContent(parts=parts))\n            elif message.role == \"assistant\":\n                google_messages.append(ModelContent(parts=parts))\n            else:\n                msg = f\"Invalid message role: {message.role}\"\n                raise ValueError(msg)\n            continue\n\n        # Handle single content item\n        part = _sampling_content_to_google_genai_part(content)\n\n        if message.role == \"user\":\n            google_messages.append(UserContent(parts=[part]))\n        elif message.role == \"assistant\":\n            google_messages.append(ModelContent(parts=[part]))\n        else:\n            msg = f\"Invalid message role: {message.role}\"\n            raise ValueError(msg)\n\n    return google_messages\n\n\ndef _get_candidate_from_response(response: GenerateContentResponse) -> Candidate:\n    \"\"\"Extract the first candidate from a response.\"\"\"","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py#L279-L315","documentation":"_convert_messages_to_google_genai_content raises ValueError when a sampling message has a role other than 'user' or 'assistant'. Google GenAI Content only defines user/model roles, so any other role (e.g. a future or malformed MCP role) cannot be mapped.","triggerScenarios":"A sampling request message has role set to something other than the MCP-standard 'user' or 'assistant' — e.g. hand-built SamplingMessage with a typo like 'system' or 'tool'.","commonSituations":"Constructing SamplingMessage manually with 'system' role (system prompts belong in params.systemPrompt, not messages); copying roles from OpenAI-style payloads; MCP spec changes.","solutions":["Use only 'user' or 'assistant' roles in sampling messages; move system text to SamplingParams.systemPrompt.","Fix the server side if it emits non-standard roles.","Catch ValueError and remap unknown roles to 'user' in your sampling callback.","Upgrade fastmcp-slim if a new MCP role needs official mapping."],"exampleFix":"// before\nSamplingMessage(role=\"system\", content=TextContent(type=\"text\", text=\"Be concise\"))\n// after\nSamplingMessage(role=\"user\", content=TextContent(type=\"text\", text=\"Be concise\"))\n# or set params.systemPrompt = \"Be concise\"","handlingStrategy":"validation","validationCode":"def validate_roles(messages):\n    for m in messages:\n        if m.role not in (\"user\", \"assistant\"):\n            raise ValueError(f\"Invalid role for Gemini handler: {m.role!r}\")","typeGuard":"def has_valid_role(m) -> bool:\n    return getattr(m, \"role\", None) in (\"user\", \"assistant\")","tryCatchPattern":"try:\n    result = await handler(messages, params, context)\nexcept ValueError as e:\n    if \"Invalid message role\" in str(e):\n        messages = [m if m.role in (\"user\", \"assistant\") else m.model_copy(update={\"role\": \"user\"}) for m in messages]\n        result = await handler(messages, params, context)\n    else:\n        raise","preventionTips":["Never use 'system' role in sampling messages — use params.systemPrompt","Only construct SamplingMessage with 'user' or 'assistant'","Validate server-emitted sampling requests before handling","Watch MCP spec changes for new roles and update fastmcp-slim"],"tags":["google-genai","sampling","message-role","valueerror"],"backgroundTag":"invalid-message-role","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}