{"record":{"id":"ed895d2b1800d680","repo":"BerriAI/litellm","slug":"messages-must-be-a-list-ed895d","errorCode":null,"errorMessage":"messages must be a list","messagePattern":"messages must be a list","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/bedrock/count_tokens/transformation.py","lineNumber":267,"sourceCode":"        Args:\n            request_data: The request payload\n\n        Raises:\n            ValueError: If the request is invalid\n        \"\"\"\n        if not request_data.get(\"model\"):\n            raise ValueError(\"model parameter is required\")\n\n        input_type: Final = self._detect_input_type(request_data)\n\n        if input_type == \"converse\":\n            # Validate Converse format (messages-based)\n            messages: Final = request_data.get(\"messages\", [])\n            if not messages:\n                raise ValueError(\"messages parameter is required for Converse input\")\n\n            if not isinstance(messages, list):\n                raise ValueError(\"messages must be a list\")\n\n            for i, message in enumerate(messages):\n                if not isinstance(message, dict):\n                    raise ValueError(f\"Message {i} must be a dictionary\")\n\n                if \"role\" not in message:\n                    raise ValueError(f\"Message {i} must have a 'role' field\")\n\n                if \"content\" not in message:\n                    raise ValueError(f\"Message {i} must have a 'content' field\")\n        else:\n            # For InvokeModel format, we need at least some content to count tokens\n            # The content structure varies by model, so we do minimal validation\n            if len(request_data) <= 1:  # Only has 'model' field\n                raise ValueError(\"Request must contain content to count tokens\")\n","sourceCodeStart":249,"sourceCodeEnd":283,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/bedrock/count_tokens/transformation.py#L249-L283","documentation":"Raised by validate_count_tokens_request when a Converse-format request supplies 'messages' whose Python type is not list. The Converse contract requires an ordered list of message objects; strings, dicts, or None fail this structural check before token counting starts.","triggerScenarios":"Passing messages as a single dict ({'role': 'user', ...}) instead of a one-element list; passing a raw string ('hello'); passing None; double-wrapping like {'messages': {'messages': [...]}}.","commonSituations":"Porting code from APIs that accept a lone message object; template/ORM layers that collapse single-element lists; copy-paste from chat-completions snippets that build messages differently.","solutions":["Wrap a single message in a list: messages=[msg] instead of messages=msg","If the content came from JSON, ensure you parsed it (json.loads) rather than passing the serialized string","Add a unit assertion isinstance(messages, list) at request-build time"],"exampleFix":"# before\nbody = {'model': 'bedrock/...', 'messages': {'role': 'user', 'content': 'hello'}}\n\n# after\nbody = {'model': 'bedrock/...', 'messages': [{'role': 'user', 'content': 'hello'}]}","handlingStrategy":"type-guard","validationCode":"def assert_messages_is_list(body: dict) -> None:\n    if 'messages' in body and not isinstance(body['messages'], list):\n        raise TypeError(f\"'messages' must be a list, got {type(body['messages']).__name__}\")","typeGuard":"from typing import TypeGuard\n\ndef is_message_list(value: object) -> TypeGuard[list[dict]]:\n    return isinstance(value, list) and len(value) > 0 and all(isinstance(m, dict) for m in value)","tryCatchPattern":"try:\n    handler.count_tokens(body)\nexcept ValueError as e:\n    if 'messages must be a list' in str(e):\n        single = body['messages']\n        body['messages'] = [single] if isinstance(single, dict) else list(single)\n        handler.count_tokens(body)\n    else:\n        raise","preventionTips":["Normalize single dicts into one-element lists at the boundary of your app","Type request builders with TypedDict/Pydantic so mismatches fail at lint/test time","Assert list-ness in request-factory unit tests"],"tags":["bedrock","count-tokens","validation","type-error","converse"],"backgroundTag":"schema-validation-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}