run-llama/llama_index · error · ValueError

LLM only supports text inputs

Error message

LLM only supports text inputs

What it means

Raised by BaseLLM.convert_chat_messages when a ChatMessage's content is a list of blocks and at least one block is not a TextBlock. This base implementation flattens list content into a plain string for LLMs that only accept text, so ImageBlock/AudioBlock/etc. in the list are unsupported.

Source

Thrown at llama-index-core/llama_index/core/base/llms/base.py:80

        Emitted via instrumentation events and callback payloads, so it must
        never contain credentials (e.g. ``api_key``) or auth headers. Defaults
        to the model's metadata; subclasses may override to add safe details.
        """
        return {"class_name": self.class_name(), **self.metadata.model_dump()}

    def convert_chat_messages(self, messages: Sequence[ChatMessage]) -> List[Any]:
        """Convert chat messages to an LLM specific message format."""
        converted_messages = []
        for message in messages:
            if isinstance(message.content, str):
                converted_messages.append(message)
            elif isinstance(message.content, List):
                content_string = ""
                for block in message.content:
                    if isinstance(block, TextBlock):
                        content_string += block.text
                    else:
                        raise ValueError("LLM only supports text inputs")
                message.content = content_string
                converted_messages.append(message)
            else:
                raise ValueError(f"Invalid message content: {message.content!s}")

        return converted_messages

    @abstractmethod
    def chat(self, messages: Sequence[ChatMessage], **kwargs: Any) -> ChatResponse:
        """
        Chat endpoint for LLM.

        Args:
            messages (Sequence[ChatMessage]):
                Sequence of chat messages.
            kwargs (Any):
                Additional keyword arguments to pass to the LLM.

View on GitHub (pinned to afd0fef371)

Solutions

  1. Use a multimodal LLM class that overrides convert_chat_messages (e.g. OpenAI/AzureOpenAI multimodal LLMs) when you need image/audio blocks.
  2. Strip non-text blocks before calling a text-only LLM: keep only TextBlock entries and join their .text.
  3. Pass content as a plain string for text-only models: ChatMessage.from_str(...) or content="...".

Example fix

# before
msgs = [ChatMessage(blocks=[TextBlock(text="describe"), ImageBlock(image=bytes(...))], role=MessageRole.USER)]
resp = text_only_llm.chat(msgs)

# after
msgs = [ChatMessage(content="describe", role=MessageRole.USER)]
resp = text_only_llm.chat(msgs)
# or switch to a multimodal LLM: Settings.llm = OpenAI(model="gpt-4o")
Defensive patterns

Strategy: validation

Validate before calling

from llama_index.core.base.llms.types import TextBlock
texts = [b.text for b in msg.blocks if isinstance(b, TextBlock)]
safe_msg = ChatMessage(content="\n".join(texts), role=msg.role)

Type guard

def is_text_only(msg: ChatMessage) -> bool:
    return isinstance(msg.content, str) or all(
        hasattr(b, "text") for b in (msg.blocks or [])
    )

Try / catch

try:
    resp = llm.chat(msgs)
except ValueError as e:
    if "text inputs" in str(e):
        msgs = [strip_to_text(m) for m in msgs]
        resp = llm.chat(msgs)

Prevention

When it happens

Trigger: Calling llm.chat(messages=[ChatMessage(blocks=[TextBlock(...), ImageBlock(...)])]) on an LLM class that uses the base convert_chat_messages (text-only LLMs, e.g. some local/open-source implementations) instead of a multimodal one.

Common situations: Sending multimodal messages to a text-only model; reusing a multimodal prompt with a non-multimodal LLM after swapping Settings.llm; older code where content strings became block lists after the multi-block ChatMessage refactor.

Related errors


AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15). Data as JSON: /api/errors/503f1f47cacb7279. Report an issue: GitHub.