xai-org/x-algorithm · error · ValueError

Invalid Role

Error message

Invalid Role

What it means

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.

Source

Thrown at grox/core/lm/convo.py:255

                                image_url=f"data:image/jpeg;base64,{storyboard_b64}",
                                detail="high",
                            )
                        )

        flush_text_buffer()
        return result

    def interleaveToEapi(self) -> chat_pb2.Message:
        interleaved = self.convert_grox_content_to_xai_content_list(self.content)
        match self.role:
            case Role.USER | Role.HUMAN:
                return user(*interleaved)
            case Role.ASSISTANT:
                return assistant(*interleaved)
            case Role.SYSTEM:
                return system(*interleaved)
            case _:
                raise ValueError("Invalid Role")

    def to_prompt(self) -> str:
        for c in self.content:
            if (
                not isinstance(c, str)
                and not isinstance(c, Image)
                and not isinstance(c, Video)
            ):
                raise ValueError(
                    f"Message content must be a str, Image, or Video, got {type(c)}"
                )
        msg = "\n".join([c for c in self.content if isinstance(c, str)])
        return (
            f"{self.role.value}: {msg}{self.separator}"
            if not self.is_empty()
            else f"{self.role.value}: "
        )

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Inspect the failing item's role value (log the repr) and normalize it to one of the supported roles before conversion.
  2. Filter or map unsupported roles (e.g. tool messages) into assistant/user content upstream.
  3. Upgrade the library if a newer version supports the extended role set.
  4. When constructing items, use the Role enum members rather than strings.

Example fix

# before
msg = convo.interleaveToEapi()  # item.role == 'tool'

# after
for item in convo.content:
    if item.role not in (Role.USER, Role.ASSISTANT, Role.SYSTEM):
        item.role = Role.ASSISTANT  # or drop the item
msg = convo.interleaveToEapi()
Defensive patterns

Strategy: type-guard

Validate before calling

from grox.core.lm.convo import Role

supported = {Role.USER, Role.ASSISTANT, Role.SYSTEM}
for item in convo.content:
    if item.role not in supported:
        item.role = Role.ASSISTANT  # or drop the item

Type guard

from grox.core.lm.convo import Role

def role_is_supported(role) -> bool:
    return role in {Role.USER, Role.ASSISTANT, Role.SYSTEM}

Try / catch

try:
    msgs = convo.interleaveToEapi()
except ValueError as e:
    if "Invalid Role" in str(e):
        raise ValueError(f"unsupported role in conversation; normalize tool/unknown roles first") from e
    raise

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/4d46032bfcca6c90. Report an issue: GitHub.