BerriAI/litellm · critical · AuthenticationError
GitHub Copilot API key is required. Please authenticate via
Error message
GitHub Copilot API key is required. Please authenticate via OAuth Device Flow.
What it means
Raised in the Copilot embedding transformation's validate_environment when the OAuth-obtained API key is falsy after get_api_key() returns (None or empty string). This branch is defensive: get_api_key() normally raises on failure rather than returning empty, so hitting this means the authenticator returned an empty value without error — e.g. a hand-placed api-key.json whose 'token' is an empty string. The message directs you to the OAuth Device Flow.
Source
Thrown at litellm/llms/github_copilot/embedding/transformation.py:66
def validate_environment(
self,
headers: dict,
model: str,
messages: list,
optional_params: dict,
litellm_params: dict,
api_key: str | None = None,
api_base: str | None = None,
) -> dict:
"""
Validate environment and set up headers for GitHub Copilot API.
"""
try:
# Get GitHub Copilot API key via OAuth
api_key = self.authenticator.get_api_key()
if not api_key:
raise AuthenticationError(
model=model,
llm_provider="github_copilot",
message="GitHub Copilot API key is required. Please authenticate via OAuth Device Flow.",
)
# Get default headers
default_headers: Final = get_copilot_default_headers(api_key)
# Merge with existing headers (user's extra_headers take priority)
merged_headers: Final = {**default_headers, **headers}
verbose_logger.debug("GitHub Copilot Embedding API: Successfully configured headers for model %s", model)
return merged_headers
except GetAPIKeyError as e:
raise AuthenticationError(
model=model,View on GitHub (pinned to 6c2dcb801b)
Solutions
- Delete the corrupted api-key.json cache and let the authenticator refresh/re-authenticate from scratch.
- Complete the GitHub Copilot OAuth device flow (litellm --login github_copilot, then verify at github.com/login/device).
- If injecting a pre-baked token cache in deployments, validate it contains a non-empty 'token' before shipping.
- Re-run the embedding call after the cache is repopulated.
Example fix
# before: hand-crafted cache with empty token
# ~/.litellm/github_copilot/api-key.json: {"token": "", "expires_at": 0}
litellm.embedding(model="github_copilot/text-embedding-3-small", input=["hello"])
# after: remove the broken cache; authenticate via device flow so token is real
import pathlib, shutil
cache = pathlib.Path("~/.litellm/github_copilot/api-key.json").expanduser()
if cache.exists(): cache.unlink()
# litellm --login github_copilot (one-time)
litellm.embedding(model="github_copilot/text-embedding-3-small", input=["hello"]) Defensive patterns
Strategy: validation
Validate before calling
import json, pathlib
cache = pathlib.Path("~/.litellm/github_copilot/api-key.json").expanduser()
if cache.exists():
token = json.loads(cache.read_text()).get("token")
if not token:
cache.unlink()
print("removed empty-token cache; device-flow login will re-create it") Type guard
def copilot_cache_has_token(cache_path: pathlib.Path) -> bool:
try:
return bool(json.loads(cache_path.read_text()).get("token"))
except (FileNotFoundError, json.JSONDecodeError, OSError):
return False Try / catch
from litellm.exceptions import AuthenticationError
try:
emb = litellm.embedding(model="github_copilot/text-embedding-3-small", input=["hi"])
except AuthenticationError as e:
if "authenticate via OAuth Device Flow" in str(e):
raise SystemExit("Run 'litellm --login github_copilot' once, then retry") from e
raise Prevention
- Validate any deployed token cache contains a non-empty token.
- Never template api-key.json by hand.
- Use the device flow as the only path that writes the cache.
- Add a CI check that rejects empty-string secrets bound for the Copilot cache.
When it happens
Trigger: Calling litellm.embedding(..., model="github_copilot/...") when the token cache contains an api-key.json with an empty/None 'token' value, or the authenticator path returns an empty key. Any real refresh/expiry failure would raise GetAPIKeyError instead (caught separately below this check).
Common situations: Users manually creating or editing api-key.json templates and leaving token blank; secrets managers injecting an empty string as the cached token; partial writes to the cache file from a killed process.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- str(e)
- GitHub Copilot API key is required. Please authenticate via
- Failed to get access token after 3 attempts
- Failed to refresh API key: {e}
- str(e)
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/3c03e99f0c942031.
Report an issue: GitHub.