{"record":{"id":"e05ad3bac8264ba3","repo":"VectifyAI/PageIndex","slug":"messages-must-be-a-non-empty-string-or-a-list-of-m-e05ad3","errorCode":null,"errorMessage":"messages must be a non-empty string or a list of message dicts.","messagePattern":"messages must be a non-empty string or a list of message dicts\\.","errorType":"validation","errorClass":"PageIndexAPIError","httpStatus":null,"severity":"error","filePath":"pageindex/local_chat.py","lineNumber":1029,"sourceCode":"                 top_p: Optional[float] = None,\n                 top_k: Optional[int] = None,\n                 stop_sequences: Optional[list[str]] = None,\n                 max_turns: Optional[int] = None,\n                 thinking: Optional[dict] = None,\n                 extra_body: Optional[dict] = None,\n                 extra_headers: Optional[dict] = None,\n                 backend: Optional[dict] = None,\n                 ) -> Union[dict, Iterator[Any]]:\n    from .integrations.anthropic_sdk import build_anthropic_tools\n\n    _require_anthropic()\n    import anthropic\n    _validate_max_turns(max_turns)\n    if isinstance(messages, str) and messages.strip():\n        messages = [{\"role\": \"user\", \"content\": messages}]\n    if (not isinstance(messages, list) or not messages\n            or not all(isinstance(message, dict) for message in messages)):\n        raise PageIndexAPIError(\"messages must be a non-empty string or a \"\n                                \"list of message dicts.\")\n    scope = client._local_doc_scope(doc_id)\n    block = _doc_block(client, doc_id, scoped=scope is not None)\n    prepared = [dict(message) for message in messages]\n    passthrough = {key: value for key, value in {\n        \"temperature\": temperature, \"top_p\": top_p, \"top_k\": top_k,\n        \"stop_sequences\": stop_sequences, \"thinking\": thinking,\n        \"extra_body\": extra_body, \"extra_headers\": extra_headers,\n    }.items() if value is not None}\n    system_blocks = _anthropic_system(client, system, block)\n    # Top-level cache_control: the server re-marks the newest block each\n    # turn, so the loop re-reads the growing conversation from cache.\n    # Counts toward the 4-breakpoint limit (live-verified 400 past it).\n    cached: dict[str, Any] = (\n        {\"cache_control\": {\"type\": \"ephemeral\"}}\n        if _cache_marks(system_blocks, prepared) < 4 else {})\n    # Tools before the transport: on a bridge client building them is\n    # network I/O, and a failure there must not strand the client below.","sourceCodeStart":1011,"sourceCodeEnd":1047,"githubUrl":"https://github.com/VectifyAI/PageIndex/blob/afb5e119766630af6014b04fe8b53357527bc05e/pageindex/local_chat.py#L1011-L1047","documentation":"run_messages() normalizes its input: a non-blank string becomes a single user message, otherwise messages must be a non-empty list of dicts. This guard fires before any network traffic when the input is neither — e.g. an empty string, empty list, a list containing non-dicts, or a bare dict/tuple.","triggerScenarios":"client.messages(\"\"), client.messages([]), client.messages([\"hello\"]) (list of strings), or client.messages(None) — any input that is not a non-blank string or a list of message dicts.","commonSituations":"Forwarding user input that can be empty (a blank chat box); passing [{'role': 'user', 'content': ...}, 'extra'] by accident; template bugs producing None.","solutions":["Ensure messages is a non-empty string or a list of dicts like [{'role': 'user', 'content': '...'}]","Filter/validate upstream user input before calling messages()","If the list may be empty, skip the call entirely (there is nothing to send)"],"exampleFix":"# before\nclient.messages(user_input)  # user_input may be \"\"\n# after\nif isinstance(user_input, str) and user_input.strip():\n    client.messages(user_input)","handlingStrategy":"validation","validationCode":"def valid_messages(msgs) -> bool:\n    if isinstance(msgs, str):\n        return bool(msgs.strip())\n    return (isinstance(msgs, list) and bool(msgs)\n            and all(isinstance(m, dict) for m in msgs))\n\nif not valid_messages(user_msgs):\n    return  # nothing to send","typeGuard":"def is_message_list(v) -> bool:\n    return (isinstance(v, list) and len(v) > 0\n            and all(isinstance(m, dict) and 'role' in m and 'content' in m for m in v))","tryCatchPattern":null,"preventionTips":["Guard blank user input before calling messages()","Wrap single blocks/messages in the documented dict shape"],"tags":["validation","messages","input","anthropic"],"backgroundTag":"invalid-argument-type","analyzedSha":"afb5e119766630af6014b04fe8b53357527bc05e","analyzedAt":"2026-08-27T11:20:48.519Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}