VectifyAI/PageIndex · error · PageIndexAPIError

messages must be a non-empty list.

Error message

messages must be a non-empty list.

What it means

chat_completions requires messages to be a non-empty Python list. None, a string, a dict, or an empty list all fail this upfront validation before any model call.

Source

Thrown at pageindex/local_chat.py:63

    """Text of a system/developer message: a string, or text parts joined."""
    if isinstance(content, str):
        return content
    if isinstance(content, list):
        texts = [part.get("text") for part in content
                 if isinstance(part, dict) and isinstance(part.get("text"), str)]
        if texts:
            return "\n".join(texts)
    raise PageIndexAPIError(
        "system message content must be a string or a list of text parts."
    )


def _split_chat_messages(messages) -> "tuple[list[str], list[dict]]":
    """Validate the chat_completions surface's messages: system/developer
    content joins the managed instructions; user/assistant history passes
    through. Tool-history round-trips belong to responses()/messages()."""
    if not isinstance(messages, list) or not messages:
        raise PageIndexAPIError("messages must be a non-empty list.")
    system_texts: list[str] = []
    history: list[dict] = []
    for message in messages:
        if not isinstance(message, dict) or "role" not in message:
            raise PageIndexAPIError(
                "Each message must be a dict with 'role' and 'content'.")
        role = message["role"]
        if role in ("system", "developer"):
            system_texts.append(_system_text(message.get("content")))
        elif role in ("user", "assistant"):
            content = message.get("content")
            if not isinstance(content, str):
                raise PageIndexAPIError(
                    "chat_completions content must be a string; for "
                    "structured items use responses() or messages()."
                )
            history.append({"role": role, "content": content})
        else:

View on GitHub (pinned to afb5e11976)

Solutions

  1. Ensure the list has at least one message, typically the user turn
  2. Guard: if not messages: append a default user message or return early
  3. Parse-then-validate external payloads before calling

Example fix

# before
client.chat_completions(model=m, messages=history or [])

# after
if not history:
    raise ValueError("conversation history is empty")
client.chat_completions(model=m, messages=history)
Defensive patterns

Strategy: validation

Validate before calling

assert isinstance(messages, list) and messages, 'messages must be a non-empty list'

Type guard

def is_valid_messages(msgs) -> bool:
    return isinstance(msgs, list) and len(msgs) > 0

Try / catch

null

Prevention

When it happens

Trigger: Calling chat_completions(messages=[]), messages=None, or messages="hello" (string shortcut unsupported here).

Common situations: Template code producing empty history on first turn, passing a JSON-decoded value that turned out to be an object, forgetting to include the user's message after building system prompt.

Related errors


AI-assisted analysis of VectifyAI/PageIndex@afb5e11976 (2026-08-27). Data as JSON: /api/errors/685dc57de982eb4d. Report an issue: GitHub.