{"record":{"id":"4d46032bfcca6c90","repo":"xai-org/x-algorithm","slug":"invalid-role","errorCode":null,"errorMessage":"Invalid Role","messagePattern":"Invalid Role","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"grox/core/lm/convo.py","lineNumber":255,"sourceCode":"                                image_url=f\"data:image/jpeg;base64,{storyboard_b64}\",\n                                detail=\"high\",\n                            )\n                        )\n\n        flush_text_buffer()\n        return result\n\n    def interleaveToEapi(self) -> chat_pb2.Message:\n        interleaved = self.convert_grox_content_to_xai_content_list(self.content)\n        match self.role:\n            case Role.USER | Role.HUMAN:\n                return user(*interleaved)\n            case Role.ASSISTANT:\n                return assistant(*interleaved)\n            case Role.SYSTEM:\n                return system(*interleaved)\n            case _:\n                raise ValueError(\"Invalid Role\")\n\n    def to_prompt(self) -> str:\n        for c in self.content:\n            if (\n                not isinstance(c, str)\n                and not isinstance(c, Image)\n                and not isinstance(c, Video)\n            ):\n                raise ValueError(\n                    f\"Message content must be a str, Image, or Video, got {type(c)}\"\n                )\n        msg = \"\\n\".join([c for c in self.content if isinstance(c, str)])\n        return (\n            f\"{self.role.value}: {msg}{self.separator}\"\n            if not self.is_empty()\n            else f\"{self.role.value}: \"\n        )\n","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/grox/core/lm/convo.py#L237-L273","documentation":"interleaveToEapi converts a conversation's content items into Eapi messages, branching on each item's Role (USER/ASSISTANT/SYSTEM). The match has an exhaustive-looking fallback, so hitting 'Invalid Role' means a role value outside the known enum reached this code — e.g. a new/unknown role or a role-like string.","triggerScenarios":"A conversation item whose role is not Role.USER, Role.ASSISTANT, or Role.SYSTEM (e.g. a 'tool'/'function' role, a raw string, or an extended enum member added in a newer version).","commonSituations":"Version mismatch where a newer producer emits roles this build doesn't handle; hand-constructed conversation items with string roles; serializing/deserializing roles losing enum type so equality checks fail.","solutions":["Inspect the failing item's role value (log the repr) and normalize it to one of the supported roles before conversion.","Filter or map unsupported roles (e.g. tool messages) into assistant/user content upstream.","Upgrade the library if a newer version supports the extended role set.","When constructing items, use the Role enum members rather than strings."],"exampleFix":"# before\nmsg = convo.interleaveToEapi()  # item.role == 'tool'\n\n# after\nfor item in convo.content:\n    if item.role not in (Role.USER, Role.ASSISTANT, Role.SYSTEM):\n        item.role = Role.ASSISTANT  # or drop the item\nmsg = convo.interleaveToEapi()","handlingStrategy":"type-guard","validationCode":"from grox.core.lm.convo import Role\n\nsupported = {Role.USER, Role.ASSISTANT, Role.SYSTEM}\nfor item in convo.content:\n    if item.role not in supported:\n        item.role = Role.ASSISTANT  # or drop the item","typeGuard":"from grox.core.lm.convo import Role\n\ndef role_is_supported(role) -> bool:\n    return role in {Role.USER, Role.ASSISTANT, Role.SYSTEM}","tryCatchPattern":"try:\n    msgs = convo.interleaveToEapi()\nexcept ValueError as e:\n    if \"Invalid Role\" in str(e):\n        raise ValueError(f\"unsupported role in conversation; normalize tool/unknown roles first\") from e\n    raise","preventionTips":["Construct conversation items only with the Role enum members.","Normalize third-party message roles (tool/function) to assistant or user at ingestion.","Pin library versions so new role enums don't reach old converters silently."],"tags":["python","enum","conversation","mapping"],"backgroundTag":"unsupported-enum-value","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}