{"record":{"id":"fd633890dc7ed2f0","repo":"microsoft/autogen","slug":"unrecognized-message-role-message-role","errorCode":null,"errorMessage":"Unrecognized message role: {message.role}","messagePattern":"Unrecognized message role: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-ext/src/autogen_ext/tools/mcp/_host/_sampling.py","lineNumber":85,"sourceCode":"\n    Raises:\n        ValueError: If message role is not recognized\n        AssertionError: If assistant message content is not text\n    \"\"\"\n    content = parse_sampling_content(message.content, model_info=model_info)\n    if message.role == \"user\":\n        return UserMessage(\n            source=\"user\",\n            content=[content],\n        )\n    elif message.role == \"assistant\":\n        assert isinstance(content, str), \"Assistant messages only support string content.\"\n        return AssistantMessage(\n            source=\"assistant\",\n            content=content,\n        )\n    else:\n        raise ValueError(f\"Unrecognized message role: {message.role}\")\n\n\ndef finish_reason_to_stop_reason(finish_reason: FinishReasons) -> StopReason:\n    \"\"\"Convert AutoGen finish reasons to MCP stop reasons.\n\n    Args:\n        finish_reason: AutoGen completion finish reason\n\n    Returns:\n        Corresponding MCP stop reason\n    \"\"\"\n    if finish_reason == \"stop\":\n        return \"endTurn\"\n    elif finish_reason == \"length\":\n        return \"maxTokens\"\n    else:\n        return finish_reason\n","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-ext/src/autogen_ext/tools/mcp/_host/_sampling.py#L67-L103","documentation":"parse_sampling_message maps MCP sampling messages to AutoGen messages and accepts only role 'user' or 'assistant'; any other role string raises ValueError(f'Unrecognized message role: {message.role}'). The MCP sampling spec only defines these two roles, so this error indicates a malformed or protocol-violating message from the server.","triggerScenarios":"An MCP server sends a sampling message with role='system', 'tool', 'function', or a custom string; parse_sampling_message falls through user/assistant branches and raises.","commonSituations":"A hand-written or experimental MCP server reusing LLM chat roles (system/tool) in createMessage payloads; server code built against a different understanding of the sampling schema; typos like 'User'.","solutions":["Fix the server to send only role 'user' or 'assistant' in sampling messages (system prompts go in the separate systemPrompt field of the sampling request).","If a system prompt is intended, move it into the sampling request's systemPrompt parameter instead of a message entry.","Upgrade the server library (e.g. official typescript/python MCP SDK) which enforces the role union.","As a host-side mitigation, catch the ValueError per message and reject that sampling request cleanly."],"exampleFix":"# server side — before\nmessages = [types.SamplingMessage(role=\"system\", content=text_block)]\n\n# server side — after\nresult = await session.create_message(\n    messages=[types.SamplingMessage(role=\"user\", content=text_block)],\n    system_prompt=\"You are a helpful assistant.\n    max_tokens=1024,\n)","handlingStrategy":"validation","validationCode":"ALLOWED_ROLES = {\"user\", \"assistant\"}\nif message.role not in ALLOWED_ROLES:\n    raise ValueError(f\"sampling message role must be one of {sorted(ALLOWED_ROLES)}, got {message.role!r}\")","typeGuard":"from typing import Any, TypeGuard\n\ndef is_supported_sampling_role(role: Any) -> TypeGuard[str]:\n    return role in {\"user\", \"assistant\"}","tryCatchPattern":"try:\n    msg = parse_sampling_message(message, model_info)\nexcept ValueError as e:\n    if \"Unrecognized message role\" in str(e):\n        return error_result(\"malformed sampling message\")\n    raise","preventionTips":["Build servers with the official MCP SDK, which enforces the role union at type level.","Put system prompts in the sampling request's systemPrompt field, never as a message.","Validate inbound sampling payloads in the host before conversion."],"tags":["mcp","sampling","message-role","protocol"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}