langchain-ai/langchain · error · ValueError

Got unsupported message type: {m}

Error message

Got unsupported message type: {m}

What it means

Raised by the internal `_get_message_type_str` helper used by `get_buffer_string` when a message is not one of the known types (`HumanMessage`, `AIMessage`, `SystemMessage`, `FunctionMessage`, `ToolMessage`, `ChatMessage`). `get_buffer_string` renders a chat history as a single string, so it must map every message to a role prefix.

Source

Thrown at libs/core/langchain_core/messages/utils.py:284

        The type string for the message element.

    Raises:
        ValueError: If an unsupported message type is encountered.
    """
    if isinstance(m, HumanMessage):
        return human_prefix.lower()
    if isinstance(m, AIMessage):
        return ai_prefix.lower()
    if isinstance(m, SystemMessage):
        return system_prefix.lower()
    if isinstance(m, FunctionMessage):
        return function_prefix.lower()
    if isinstance(m, ToolMessage):
        return tool_prefix.lower()
    if isinstance(m, ChatMessage):
        return m.role
    msg = f"Got unsupported message type: {m}"
    raise ValueError(msg)


def get_buffer_string(
    messages: Sequence[BaseMessage],
    human_prefix: str = "Human",
    ai_prefix: str = "AI",
    *,
    system_prefix: str = "System",
    function_prefix: str = "Function",
    tool_prefix: str = "Tool",
    message_separator: str = "\n",
    format: Literal["prefix", "xml"] = "prefix",  # noqa: A002
) -> str:
    r"""Convert a sequence of messages to strings and concatenate them into one string.

    Args:
        messages: Messages to be converted to strings.
        human_prefix: The prefix to prepend to contents of `HumanMessage`s.

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Represent custom roles with `ChatMessage(content=..., role='my_role')`, which is handled via its `role` attribute
  2. Convert custom messages to one of the six supported classes before calling `get_buffer_string`
  3. Write your own buffer-string function if you truly need custom prefixes for new message classes

Example fix

# before
class MyMessage(BaseMessage): ...
get_buffer_string([MyMessage(content='hi')])

# after
from langchain_core.messages import ChatMessage
get_buffer_string([ChatMessage(content='hi', role='custom')])
Defensive patterns

Strategy: type-guard

Validate before calling

from langchain_core.messages import (HumanMessage, AIMessage, SystemMessage,
    FunctionMessage, ToolMessage, ChatMessage)

SUPPORTED = (HumanMessage, AIMessage, SystemMessage, FunctionMessage, ToolMessage, ChatMessage)

def all_renderable(messages) -> bool:
    return all(isinstance(m, SUPPORTED) for m in messages)

Type guard

def is_buffer_string_safe(m) -> bool:
    return isinstance(m, (HumanMessage, AIMessage, SystemMessage,
                          FunctionMessage, ToolMessage, ChatMessage))

Prevention

When it happens

Trigger: Calling `get_buffer_string(messages)` (or a prompt template that uses it) with a custom `BaseMessage` subclass that is none of the six recognized classes.

Common situations: Defining a custom message class for a bespoke agent protocol and feeding a history containing it into `get_buffer_string`; third-party libraries adding novel message types that predate this check.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/700afa82d7dc3e19. Report an issue: GitHub.