{"record":{"id":"dce64efde846b5ad","repo":"microsoft/semantic-kernel","slug":"invalid-message-role-message-role-value-allow-dce64e","errorCode":null,"errorMessage":"Invalid message role `{message.role.value}`. Allowed roles are {allowed_message_roles}.","messagePattern":"Invalid message role `(.+?)`\\. Allowed roles are (.+?)\\.","errorType":"exception","errorClass":"AgentExecutionException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/agents/open_ai/assistant_thread_actions.py","lineNumber":119,"sourceCode":"                Providing an empty list will disallow all message roles.\n            kwargs: Additional keyword arguments.\n\n        Returns:\n            The created message.\n        \"\"\"\n        from semantic_kernel.contents.chat_message_content import ChatMessageContent\n\n        if isinstance(message, str):\n            message = ChatMessageContent(role=AuthorRole.USER, content=message)\n\n        if any(isinstance(item, FunctionCallContent) for item in message.items):\n            return None\n\n        # Set the default allowed message roles if not provided\n        if allowed_message_roles is None:\n            allowed_message_roles = [AuthorRole.USER, AuthorRole.ASSISTANT]\n        if message.role.value not in allowed_message_roles and message.role != AuthorRole.TOOL:\n            raise AgentExecutionException(\n                f\"Invalid message role `{message.role.value}`. Allowed roles are {allowed_message_roles}.\"\n            )\n\n        message_contents: list[dict[str, Any]] = get_message_contents(message=message)\n\n        return await client.beta.threads.messages.create(\n            thread_id=thread_id,\n            role=\"assistant\" if message.role == AuthorRole.TOOL else message.role.value,  # type: ignore\n            content=message_contents,  # type: ignore\n            **kwargs,\n        )\n\n    # endregion\n\n    # region Invocation Methods\n\n    @classmethod\n    async def invoke(","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/agents/open_ai/assistant_thread_actions.py#L101-L137","documentation":"Same role guard as the content-generation helper, applied inside AssistantThreadActions when creating a thread message. allowed_message_roles defaults to [USER, ASSISTANT]; TOOL is always allowed. Note a string message is auto-wrapped as USER, and messages containing FunctionCallContent are short-circuited (return None) before this check. Any remaining message with a disallowed role raises AgentExecutionException.","triggerScenarios":"Submitting a ChatMessageContent with role SYSTEM (or another disallowed role) to the thread-actions message-create path; passing a custom allowed_message_roles list that excludes the role of a message being added.","commonSituations":"Reusing a multi-role chat history (with SYSTEM entries) as the thread's messages; building allowed_message_roles dynamically and accidentally omitting the needed role; migrating prompts that previously put system text inline.","solutions":["Pre-filter history to USER/ASSISTANT roles before passing to the assistant invoke path.","Do not pass allowed_message_roles unless you actually need to restrict; the default covers the common case.","Keep SYSTEM content in the assistant instructions, not in thread messages."],"exampleFix":"// before\nallowed = [AuthorRole.USER]\nawait actions.create_message(client, thread_id, assistant_msg, allowed_message_roles=allowed)\n# assistant_msg.role == ASSISTANT -> Invalid message role\n\n// after\nawait actions.create_message(client, thread_id, assistant_msg)  # default allows USER+ASSISTANT","handlingStrategy":"validation","validationCode":"from semantic_kernel.contents import AuthorRole\n\ndef filter_thread_messages(history):\n    allowed = {AuthorRole.USER, AuthorRole.ASSISTANT, AuthorRole.TOOL}\n    return [m for m in history if m.role in allowed]","typeGuard":"from semantic_kernel.contents import AuthorRole\n\ndef is_thread_safe_role(msg) -> bool:\n    return msg.role in (AuthorRole.USER, AuthorRole.ASSISTANT, AuthorRole.TOOL)","tryCatchPattern":null,"preventionTips":["Strip SYSTEM messages from history before submitting to a thread.","Rely on the default allowed_message_roles rather than overriding it.","Keep system text in the assistant definition."],"tags":["openai","assistant","message-role","validation","thread"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}