BerriAI/litellm · critical · ValueError

api_key is required for Gemini API calls

Error message

api_key is required for Gemini API calls

What it means

Raised in GeminiRealtimeConfig.get_complete_url when constructing the WebSocket URL for Gemini realtime sessions. The key is resolved from the explicit api_key argument, then get_api_key_from_env(); if both are None a ValueError is thrown because the key must be embedded as a ?key= query parameter on the wss:// URL. Fails before the socket is ever opened.

Source

Thrown at litellm/llms/gemini/realtime/transformation.py:135

                {"text_tokens": 0, "audio_tokens": 0},
            ),
        )
        return usage_dict

    def validate_environment(self, headers: dict, model: str, api_key: str | None = None) -> dict:
        return headers

    def get_complete_url(self, api_base: str | None, model: str, api_key: str | None = None) -> str:
        """
        Example output:
        "BACKEND_WS_URL = "wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent"";
        """
        if api_base is None:
            api_base = "wss://generativelanguage.googleapis.com"
        if api_key is None:
            api_key = get_api_key_from_env()
        if api_key is None:
            raise ValueError("api_key is required for Gemini API calls")
        api_base = api_base.replace("https://", "wss://")
        api_base = api_base.replace("http://", "ws://")
        # WebSocket connections do not support custom HTTP headers in all clients,
        # so the API key must remain as a query parameter here. This is an accepted
        # limitation; httpx is not used for WebSocket so MaskedHTTPStatusError
        # already covers the main leak vector.
        return f"{api_base}/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent?key={api_key}"

    def map_model_turn_event(self, model_turn: HttpxContentType) -> OpenAIRealtimeEventTypes:
        """
        Map the model turn event to the OpenAI realtime events.

        Returns either:
        - response.text.delta - model_turn: {"parts": [{"text": "..."}]}
        - response.audio.delta - model_turn: {"parts": [{"inlineData": {"mimeType": "audio/pcm", "data": "..."}}]}

        Assumes parts is a single element list.
        """

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Set GEMINI_API_KEY or GOOGLE_API_KEY in the environment of the process opening the realtime session.
  2. Pass api_key explicitly to the realtime call: litellm.realtime(model='gemini/...', api_key='AIza...').
  3. Print/verify env resolution (get_api_key_from_env) in the same process before connecting.

Example fix

# before
await litellm.arealtime(model='gemini/gemini-2.0-flash-live', listener=handler)

# after
import os
os.environ['GEMINI_API_KEY'] = 'AIza...'
await litellm.arealtime(
    model='gemini/gemini-2.0-flash-live',
    api_key=os.environ['GEMINI_API_KEY'],
    listener=handler,
)
Defensive patterns

Strategy: validation

Validate before calling

import os

def has_realtime_key() -> bool:
    return bool(os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY"))

if not has_realtime_key():
    raise ConfigError("GEMINI_API_KEY/GOOGLE_API_KEY required for Gemini realtime")

Try / catch

try:
    await litellm.arealtime(model="gemini/gemini-2.0-flash-live", api_key=key, listener=handler)
except ValueError as e:
    if "api_key is required" in str(e):
        abort_session_setup("missing Gemini realtime key")
    raise

Prevention

When it happens

Trigger: Starting a realtime session (e.g. litellm.realtime with model gemini-2.0-flash-live or similar) with api_key=None/empty and no GEMINI_API_KEY/GOOGLE_API_KEY environment variable set.

Common situations: Key env var present in dev shell but missing in the deployed container/service; realtime handler running in a separate worker without the env; typo in env var name; assuming the key from chat-completions config carries over to the realtime path.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/ff74fa1eff3e4b4b. Report an issue: GitHub.