{"record":{"id":"2ae11330f45b4f6c","repo":"BerriAI/litellm","slug":"bad-request-messages-is-required-for-anthropic-me","errorCode":null,"errorMessage":"Bad Request: messages is required for Anthropic Messages Request","messagePattern":"Bad Request: messages is required for Anthropic Messages Request","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py","lineNumber":171,"sourceCode":"        Translate Anthropic request params to OpenAI format, returning tool name mapping.\n\n        This method handles truncation of tool names that exceed OpenAI's 64-character\n        limit. The mapping allows restoring original names when translating responses.\n\n        Returns:\n            Tuple of (openai_request, tool_name_mapping)\n            - tool_name_mapping maps truncated tool names back to original names\n        \"\"\"\n\n        #########################################################\n        # Validate required params\n        #########################################################\n        model: Final = kwargs.pop(\"model\")\n        messages: Final = kwargs.pop(\"messages\")\n        if not model:\n            raise ValueError(\"Bad Request: model is required for Anthropic Messages Request\")\n        if not messages:\n            raise ValueError(\"Bad Request: messages is required for Anthropic Messages Request\")\n\n        #########################################################\n        # Created Typed Request Body\n        #########################################################\n        request_body: Final = AnthropicMessagesRequest(model=model, messages=messages, **kwargs)\n\n        (\n            translated_body,\n            tool_name_mapping,\n        ) = LiteLLMAnthropicMessagesAdapter().translate_anthropic_to_openai(anthropic_message_request=request_body)\n\n        return translated_body, tool_name_mapping\n\n    def translate_completion_output_params(\n        self,\n        response: ModelResponse,\n        tool_name_mapping: dict[str, str] | None = None,\n        polyfill_result: PolyfillResult | None = None,","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py#L153-L189","documentation":"Same adapter validation path as the 'model' check, but for the second required field: 'messages'. The Anthropic Messages API mandates a non-empty messages array, and this handler enforces it client-side by popping 'messages' from kwargs and rejecting falsy values before constructing the typed request.","triggerScenarios":"Calling the adapter handler with kwargs missing 'messages', messages=None, or messages=[] (empty list is falsy and also rejected). Common when a caller strips messages for logging/middleware or builds the body from a template that omits them.","commonSituations":"Proxy middleware that deserializes and re-serializes bodies and drops 'messages' on empty payloads; agent frameworks that call the completion path with only a prompt string instead of messages; empty-list edge cases in tests.","solutions":["Include a non-empty 'messages' array, e.g. [{\"role\": \"user\", \"content\": \"hello\"}], in the request body.","If the caller only has a prompt string, wrap it: messages=[{\"role\": \"user\", \"content\": prompt}].","Guard upstream: reject requests with empty messages before they reach the adapter."],"exampleFix":"# before\nkwargs = {\"model\": \"claude-sonnet-4-5\", \"max_tokens\": 100}\nhandler(**kwargs)  # ValueError: messages is required\n\n# after\nkwargs = {\n    \"model\": \"claude-sonnet-4-5\",\n    \"max_tokens\": 100,\n    \"messages\": [{\"role\": \"user\", \"content\": \"hello\"}],\n}\nhandler(**kwargs)","handlingStrategy":"validation","validationCode":"def validate_messages(body: dict) -> None:\n    msgs = body.get(\"messages\")\n    if not isinstance(msgs, list) or len(msgs) == 0:\n        raise ValueError(\"request body must include a non-empty 'messages' array\")","typeGuard":"def has_valid_messages(body: dict) -> bool:\n    msgs = body.get(\"messages\")\n    return isinstance(msgs, list) and len(msgs) > 0 and all(\n        isinstance(m, dict) and \"role\" in m and \"content\" in m for m in msgs\n    )","tryCatchPattern":"try:\n    handler(**body)\nexcept ValueError as e:\n    if \"messages is required\" in str(e):\n        return http_error(400, \"messages is required\")\n    raise","preventionTips":["Reject empty message arrays in middleware before they reach the adapter.","When wrapping a bare prompt, always convert it to a messages list of length >= 1.","Add contract tests asserting every request template contains messages."],"tags":["anthropic","validation","request-body","pass-through"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}