BerriAI/litellm · error · ValueError

Exactly one of model_id or model_name must be provided

Error message

Exactly one of model_id or model_name must be provided

What it means

Client-side guard inside ModelsManagementClient.get(): the method requires exactly one of model_id / model_name, and passing neither or both raises ValueError('Exactly one of model_id or model_name must be provided') before any network call. get() then downloads the full /v1/model/info list and filters locally by the single identifier you gave, which is why the arguments are mutually exclusive. This is a pure programming error in the caller, not a server condition.

Source

Thrown at litellm/proxy/client/models.py:178

        Get information about a specific model by its ID or name.

        Args:
            model_id (Optional[str]): ID of the model to retrieve
            model_name (Optional[str]): Name of the model to retrieve
            return_request (bool): If True, returns the prepared request object instead of executing it

        Returns:
            Union[Dict[str, Any], requests.Request]: Either the model information from the server or
            a prepared request object if return_request is True

        Raises:
            ValueError: If neither model_id nor model_name is provided, or if both are provided
            UnauthorizedError: If the request fails with a 401 status code
            NotFoundError: If the model is not found
            requests.exceptions.RequestException: If the request fails with any other error
        """
        if (model_id is None and model_name is None) or (model_id is not None and model_name is not None):
            raise ValueError("Exactly one of model_id or model_name must be provided")

        # If return_request is True, delegate to info
        if return_request:
            result: Final = self.info(return_request=True)
            assert isinstance(result, requests.Request)
            return result

        # Get all models and filter
        models: Final = self.info()
        assert isinstance(models, list)

        # Find the matching model
        for model in models:
            if (model_id and model.get("model_info", {}).get("id") == model_id) or (
                model_name and model.get("model_name") == model_name
            ):
                return model

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Pass exactly one identifier: models.get(model_id='2f23364f-...') or models.get(model_name='gpt-4o-mini')
  2. Normalize optional kwargs to None (and drop them) before calling so the guard sees exactly one
  3. If you somehow hold both, prefer model_id — UUIDs are exact matches, names can collide

Example fix

# before
model = client.models.get(model_id=None, model_name=None)  # ValueError

# after
model = (
    client.models.get(model_id=model_id)
    if model_id is not None
    else client.models.get(model_name=model_name)
)
Defensive patterns

Strategy: validation

Validate before calling

def get_model_kwargs(model_id: str | None, model_name: str | None) -> dict:
    if (model_id is None) == (model_name is None):
        raise ValueError("pass exactly one of model_id / model_name")
    return {"model_id": model_id} if model_id is not None else {"model_name": model_name}

# models.get(**get_model_kwargs(model_id, model_name))

Type guard

from typing import Any

def is_valid_get_args(model_id: Any, model_name: Any) -> bool:
    return (model_id is None) != (model_name is None)  # exactly one set

Try / catch

try:
    model = models.get(model_id=model_id, model_name=model_name)
except ValueError as e:
    if "Exactly one" in str(e):
        model = models.get(**get_model_kwargs(model_id, model_name))  # normalize and retry
    else:
        raise

Prevention

When it happens

Trigger: Calling get() with no arguments; calling get(model_id=_id, model_name=name) when both variables are populated; forwarding optional kwargs from your own wrapper into get() without normalizing absent values to None; refactor renaming one parameter so callers accidentally set both.

Common situations: Wrapper APIs that accept optional model_id and model_name and pass them straight through; dynamic callers building kwargs dicts that end up empty; copy-pasted calls carrying leftover arguments.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/935e77d26f991ac4. Report an issue: GitHub.