can1357/oh-my-pi · error · ValueError

messages must be a list

Error message

messages must be a list

What it means

parse_agent_messages expects a JSON array of agent messages (or null, meaning empty). It raises this error when the payload is any other JSON type (object, string, number, bool). The library throws so the following per-item loop can safely index and parse each element.

Source

Thrown at python/omp-rpc/src/omp_rpc/protocol.py:315

def _parse_assistant_message(payload: JsonObject, *, field: str) -> AssistantMessage:
    message = _parse_agent_message(payload, field=field)
    if message.get("role") != "assistant":
        raise ValueError(f"{field}.role must be 'assistant'")
    return cast(AssistantMessage, message)


def _parse_tool_result_message(payload: JsonObject, *, field: str) -> ToolResultMessage:
    message = _parse_agent_message(payload, field=field)
    if message.get("role") != "toolResult":
        raise ValueError(f"{field}.role must be 'toolResult'")
    return cast(ToolResultMessage, message)


def parse_agent_messages(payload: JsonValue | None) -> tuple[AgentMessage, ...]:
    if payload is None:
        return ()
    if not isinstance(payload, list):
        raise ValueError("messages must be a list")

    messages: list[AgentMessage] = []
    for index, item in enumerate(payload):
        messages.append(
            _parse_agent_message(
                _clone_json_object(item, field=f"messages[{index}]"),
                field=f"messages[{index}]",
            )
        )
    return tuple(messages)


def parse_assistant_message_event(payload: JsonObject) -> AssistantMessageEvent:
    event_type = _require_literal(
        payload.get("type"),
        _ASSISTANT_MESSAGE_EVENT_TYPE_VALUES,
        field="assistantMessageEvent.type",
    )

View on GitHub (pinned to 9690622007)

Solutions

  1. Unwrap the payload to the actual list before calling (e.g. payload["messages"])
  2. Wrap a single message in a list: [message]
  3. Check the server response shape against the protocol docs and fix the emitter or the extraction point
  4. Handle null explicitly if absence should mean empty

Example fix

// before
parse_agent_messages(result["messages"])
// after
parse_agent_messages(result)
Defensive patterns

Strategy: validation

Validate before calling

if payload is not None and not isinstance(payload, list):
    raise TypeError("expected a list of messages (or None)")

Type guard

from typing import TypeGuard

def is_message_list(v: object) -> TypeGuard[list]:
    return isinstance(v, list)

Try / catch

try:
    messages = parse_agent_messages(payload)
except ValueError:
    messages = ()  # or unwrap payload["messages"] and retry

Prevention

When it happens

Trigger: Calling parse_agent_messages with a single message object instead of a list; a server returning a wrapped object like {"messages": [...]} instead of the bare array; passing a dict from an RPC response field that should have been an array.

Common situations: Passing response['messages'] vs response directly; older server versions returning a different envelope; hand-constructed payloads in tests.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/bfdc37c3b9548f91. Report an issue: GitHub.