BerriAI/litellm · error · ValueError

api_base is required

Error message

api_base is required

What it means

ValueError raised by the Cohere v2 adapter's get_complete_url: unlike most providers, this handler does not append a path and does not synthesize a default — it requires api_base to already be set, and raises if it is None. LiteLLM normally injects the default https://api.cohere.com/v2 upstream of this call, so hitting this error means the defaulting layer was bypassed or explicitly overridden with None.

Solutions

  1. Pass api_base="https://api.cohere.com/v2" (or your proxy's equivalent full path) in the completion call
  2. If the var may be unset, fall back: api_base=os.environ.get('COHERE_API_BASE') or 'https://api.cohere.com/v2'
  3. In Router model_list entries, ensure the cohere_v2 model has api_base set or remove the key so litellm applies its default
  4. Upgrade litellm — default URL handling for cohere_v2 has changed across versions

Example fix

# before
litellm.completion(
    model="cohere_v2/command-r-plus-08-2024",
    messages=messages,
    api_base=os.environ.get("COHERE_API_BASE"),  # None when unset
)

# after
litellm.completion(
    model="cohere_v2/command-r-plus-08-2024",
    messages=messages,
    api_base=os.environ.get("COHERE_API_BASE") or "https://api.cohere.com/v2",
)
Defensive patterns

Strategy: validation

Validate before calling

import os

api_base = os.environ.get("COHERE_API_BASE") or "https://api.cohere.com/v2"

litellm.completion(
    model="cohere_v2/command-r-plus-08-2024",
    messages=messages,
    api_base=api_base,
)

Try / catch

try:
    litellm.completion(model="cohere_v2/command-r", messages=messages, api_base=maybe_base)
except ValueError as e:
    if "api_base is required" in str(e):
        litellm.completion(
            model="cohere_v2/command-r", messages=messages, api_base="https://api.cohere.com/v2"
        )
    else:
        raise

Prevention

When it happens

Trigger: Calling a cohere_v2 model (or Cohere v2 path) with api_base=None passed explicitly through router/completion kwargs, or through an integration that forwards its own api_base value without a default.

Common situations: Litellm Router configs where api_base is conditionally set and forwards None; wrapper code doing completion(..., api_base=os.environ.get('COHERE_API_BASE')) when the var is unset; custom providers routing cohere_v2 through generic paths that skip default URL resolution.

Related errors


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

Appendix: source

Thrown at litellm/llms/cohere/chat/v2_transformation.py:285

            sync_stream=sync_stream,
            json_mode=json_mode,
        )

    def get_complete_url(
        self,
        api_base: str | None,
        api_key: str | None,
        model: str,
        optional_params: dict,
        litellm_params: dict,
        stream: bool | None = None,
    ) -> str:
        """
        Get the complete URL for Cohere v2 chat completion.
        The api_base should already include the full path.
        """
        if api_base is None:
            raise ValueError("api_base is required")
        return api_base

    def get_error_class(self, error_message: str, status_code: int, headers: dict | httpx.Headers) -> BaseLLMException:
        return CohereError(status_code=status_code, message=error_message)

    def _translate_citations_to_openai_annotations(self, citations: list[dict]) -> list[ChatCompletionAnnotation]:
        """
        Transform Cohere citations to OpenAI annotations format.

        Creates separate annotations for each source in a citation, allowing multiple
        annotations with the same start/end index if they reference different sources.

        Args:
            citations: List of Cohere citation objects with format:
                {
                    "start": int,
                    "end": int,
                    "text": str,

View on GitHub (pinned to 77b7c6c40c)