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
- Set GEMINI_API_KEY or GOOGLE_API_KEY in the environment of the process opening the realtime session.
- Pass api_key explicitly to the realtime call: litellm.realtime(model='gemini/...', api_key='AIza...').
- 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
- Check env keys in the exact process that opens the WebSocket, not just at deploy time.
- Pass api_key explicitly rather than relying on env resolution.
- Fail CI smoke tests when realtime key env vars are missing.
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
- GEMINI_API_KEY or GOOGLE_API_KEY is required for Veo video g
- GEMINI_API_KEY or GOOGLE_API_KEY is required
- api_key must be provided for Vantage destination (set VANTAG
- integration_token must be provided for Vantage destination (
- ANTHROPIC_API_BASE/ANTHROPIC_BASE_URL or ANTHROPIC_API_KEY/A
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/ff74fa1eff3e4b4b.
Report an issue: GitHub.