{"record":{"id":"d2c1ef0b5f46b54a","repo":"BerriAI/litellm","slug":"bad-request-model-is-required-for-anthropic-messa","errorCode":null,"errorMessage":"Bad Request: model is required for Anthropic Messages Request","messagePattern":"Bad Request: model 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":169,"sourceCode":"    ) -> tuple[ChatCompletionRequest | None, dict[str, str]]:\n        \"\"\"\n        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,","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py#L151-L187","documentation":"Raised by LiteLLMAnthropicMessagesParamHandler when translating an Anthropic /v1/messages request body. The handler pops required kwargs and validates them before building an AnthropicMessagesRequest; 'model' is the first required field. This is a client-side 400-class validation error that fires before any provider call is made.","triggerScenarios":"Calling the Anthropic experimental pass-through adapter (translate_anthropic_request_body / the params handler in transformation.py) with a kwargs dict that lacks a 'model' key or has model=None/empty string. Typical when a caller forwards a raw request body or constructs kwargs programmatically and forgets to inject the routed model name.","commonSituations":"Custom gateways that forward client JSON straight into the adapter without mapping the 'model' field; test fixtures that only set 'messages'; typos like 'model_name' instead of 'model'; code that pops 'model' earlier for routing and forgets to re-insert it.","solutions":["Ensure the request body passed to the adapter contains a non-empty 'model' key matching the model to route to (e.g. 'claude-sonnet-4-5').","If you popped 'model' from kwargs earlier for routing decisions, pass it back in before calling the handler.","Check for typos in the key name ('model', not 'model_name' or 'modelId') in the request dict.","If using the pass-through endpoint, send the standard Anthropic Messages JSON body where 'model' is a top-level required field."],"exampleFix":"// before\nbody = {\"messages\": [{\"role\": \"user\", \"content\": \"hi\"}], \"max_tokens\": 100}\nopenai_req, mapping = handler.translate_anthropic_request_body(**body)  # ValueError\n\n// after\nbody = {\"model\": \"claude-sonnet-4-5\", \"messages\": [{\"role\": \"user\", \"content\": \"hi\"}], \"max_tokens\": 100}\nopenai_req, mapping = handler.translate_anthropic_request_body(**body)","handlingStrategy":"validation","validationCode":"def validate_anthropic_body(body: dict) -> None:\n    if not body.get(\"model\"):\n        raise ValueError(\"request body must include a non-empty 'model' field\")","typeGuard":"def is_valid_anthropic_request(body: dict) -> bool:\n    return isinstance(body.get(\"model\"), str) and bool(body[\"model\"].strip())","tryCatchPattern":"try:\n    result = handler.translate_anthropic_request_body(**body)\nexcept ValueError as e:\n    if \"model is required\" in str(e):\n        return http_error(400, \"model is required\")\n    raise","preventionTips":["Validate required Anthropic fields (model, messages, max_tokens) at the API gateway edge before forwarding.","Use a typed request model (pydantic) mirroring AnthropicMessagesRequest so omissions fail at parse time.","Never pop 'model' from kwargs for routing without re-injecting it before adapter calls."],"tags":["anthropic","validation","request-body","pass-through"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}