BerriAI/litellm · error · HTTPException
model parameter is required
Error message
model parameter is required
What it means
400 from the Anthropic-format token counting endpoint POST /v1/messages/count_tokens (litellm proxy, requires a virtual key via user_api_key_auth). The handler reads the raw JSON body and requires a truthy "model" field before building the internal TokenCountRequest; a missing, null, or empty model string fails immediately. The very next check requires non-empty "messages", so send both.
Source
Thrown at litellm/proxy/anthropic_endpoints/endpoints.py:267
"model": "claude-3-sonnet-20240229",
"messages": [{"role": "user", "content": "Hello Claude!"}]
}'
```
Returns: {"input_tokens": <number>}
"""
from litellm.proxy.proxy_server import token_counter as internal_token_counter
try:
request_data: Final = await _read_request_body(request=request)
data: Final[dict] = {**request_data}
# Extract required fields
model_name: Final = data.get("model")
messages: Final = data.get("messages", [])
if not model_name:
raise HTTPException(status_code=400, detail={"error": "model parameter is required"})
if not messages:
raise HTTPException(status_code=400, detail={"error": "messages parameter is required"})
# Create TokenCountRequest for the internal endpoint
from litellm.proxy._types import TokenCountRequest
token_request: Final = TokenCountRequest(
model=model_name,
messages=messages,
tools=data.get("tools"),
system=data.get("system"),
)
# Call the internal token counter function with direct request flag set to False
token_response: Final = await internal_token_counter(
request=token_request,
call_endpoint=True,View on GitHub (pinned to 77b7c6c40c)
Solutions
- Include a non-empty model plus messages in the JSON body: {"model": "claude-3-sonnet-20240229", "messages": [{"role": "user", "content": "Hello"}]} — note messages is checked right after model.
- Verify Content-Type: application/json and that the body is not empty/malformed before it reaches the proxy.
- If you were using the LiteLLM-internal shape, switch to the Anthropic Messages shape (model/messages/system/tools) that this endpoint mirrors.
- Check any middleware that rewrites the body and confirm it preserves the model key.
Example fix
# before
curl -X POST http://localhost:4000/v1/messages/count_tokens \
-H "Authorization: Bearer sk-..." -H "Content-Type: application/json" \
-d '{"messages": [{"role": "user", "content": "Hello"}]}'
# -> 400 model parameter is required
# after
curl -X POST http://localhost:4000/v1/messages/count_tokens \
-H "Authorization: Bearer sk-..." -H "Content-Type: application/json" \
-d '{"model": "claude-3-sonnet-20240229", "messages": [{"role": "user", "content": "Hello"}]}' Defensive patterns
Strategy: validation
Validate before calling
body = {"model": model, "messages": messages}
if not body.get("model"):
raise ValueError("count_tokens requires a non-empty 'model'")
if not body.get("messages"):
raise ValueError("count_tokens requires non-empty 'messages'")
resp = client.post(f"{base}/v1/messages/count_tokens", json=body, headers=hdr) Type guard
interface CountTokensBody {
model: string;
messages: Array<{ role: string; content: unknown }>;
}
function isCountTokensBody(b: unknown): b is CountTokensBody {
const o = b as Record<string, unknown>;
return typeof o?.model === 'string' && o.model.length > 0 && Array.isArray(o?.messages) && o.messages.length > 0;
} Try / catch
try:
resp = client.post(f"{base}/v1/messages/count_tokens", json=body, headers=hdr)
resp.raise_for_status()
except httpx.HTTPStatusError as e:
if e.response.status_code == 400 and "model parameter is required" in e.response.text:
raise ValueError("count_tokens body needs 'model' (and 'messages')") from e
raise Prevention
- Prefer the Anthropic SDK's count_tokens method — its typed params make a missing model unrepresentable.
- Validate the body has non-empty model and messages before hitting the proxy; the endpoint checks both, in that order.
- Log the outbound body shape when integrating custom middleware that may drop fields.
When it happens
Trigger: POST /v1/messages/count_tokens with a body lacking the model key ({} or {"messages": [...]}), with "model": null, or with "model": "". Also when a proxy/gateway in front of LiteLLM strips or renames the field, or when code sends the OpenAI-style prompt field instead of model+messages.
Common situations: Calling count_tokens with a hand-rolled request instead of the Anthropic SDK (the SDK forces model); migrating from /utils/token_count with a different body shape; JSON body accidentally sent as form data so parsing yields an empty dict; forwarding a request after popping the model to resolve a deployment.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- GitHub source must include 'repo' field (e.g., 'org/repo')
- URL source must include 'url' field (e.g., 'https://github.c
- git-subdir source must include 'url' field (e.g., 'https://g
- git-subdir source must include 'path' field (e.g., 'plugins/
- git-subdir 'path' must be a relative path of the form 'segme
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/71eb5635558b9df2.
Report an issue: GitHub.