BerriAI/litellm · error · Exception
Malformed API Key passed in. Ensure Key has `Bearer ` prefix
Error message
Malformed API Key passed in. Ensure Key has `Bearer ` prefix.
What it means
Raised when the request DID carry an Authorization header but the token is the empty string after stripping the `Bearer ` prefix — i.e. the header is exactly `Bearer` or `Bearer ` (trailing space). Distinguishes a present-but-empty credential (this error) from a completely absent one (`No api key passed in.`).
Source
Thrown at litellm/proxy/auth/user_api_key_auth.py:1492
elif isinstance(response, UserAPIKeyAuth):
return response
if master_key is None:
if isinstance(api_key, str):
return UserAPIKeyAuth(
api_key=api_key,
user_role=LitellmUserRoles.INTERNAL_USER,
parent_otel_span=parent_otel_span,
)
else:
return UserAPIKeyAuth(
user_role=LitellmUserRoles.INTERNAL_USER,
parent_otel_span=parent_otel_span,
)
elif api_key is None: # only require api key if master key is set
raise Exception("No api key passed in.")
elif api_key == "":
# missing 'Bearer ' prefix
raise Exception("Malformed API Key passed in. Ensure Key has `Bearer ` prefix.")
if route == "/user/auth":
if general_settings.get("allow_user_auth", False) is True:
return UserAPIKeyAuth()
else:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="'allow_user_auth' not set or set to False",
)
## Check END-USER OBJECT
_end_user_object = None
end_user_params: Final = {}
raw_end_user_id: Final = get_end_user_id_from_request_body(request_data, _safe_get_request_headers(request))
end_user_id = await resolve_and_validate_end_user_id(
raw_end_user_id=raw_end_user_id,
prisma_client=prisma_client,View on GitHub (pinned to 77b7c6c40c)
Solutions
- Fix the source of the empty value: set the key env var / secret to a real virtual key (`sk-...`) and verify with `printenv` / `echo -n "${KEY}" | wc -c`
- Guard at call sites: never build the header when the key is empty; fail fast with a clear local error
- Confirm no stray whitespace/quote artifacts — the value must be the raw key with no extra `Bearer` duplication
Example fix
# before
KEY=""
headers = {"Authorization": f"Bearer {KEY}"} # -> 'Malformed API Key passed in.'
# after
assert KEY and KEY.startswith("sk-"), "proxy key missing or empty"
headers = {"Authorization": f"Bearer {KEY}"} Defensive patterns
Strategy: validation
Validate before calling
key = os.environ.get("PROXY_KEY", "")
if not key.strip():
raise RuntimeError("PROXY_KEY is empty — would send 'Bearer ' and get malformed-key error") Type guard
def is_usable_key(key: object) -> bool:
return isinstance(key, str) and len(key.strip()) > 0 and not key.startswith("Bearer ") Try / catch
try:
client.chat.completions.create(...)
except Exception as e:
if "Malformed API Key" in str(e) and "Bearer" in str(e):
raise RuntimeError("auth header built from empty key — check env/secret values") from e
raise Prevention
- Fail fast at startup when credential env vars are empty strings, not just missing
- Never interpolate unvalidated env vars into Authorization headers
- In CI, assert secrets are non-empty before integration tests run
When it happens
Trigger: Header interpolation from an empty variable: `Authorization: Bearer ${API_KEY}` with `API_KEY=""` produces `Bearer ` and an empty extracted token; manually calling `curl -H 'Authorization: Bearer ' ...`; SDK code doing `f"Bearer {key}"` with `key = ""`.
Common situations: `.env` file defines the key but with empty value (`LITELLM_API_KEY=`); CI secrets not injected so `${KEY}` expands to empty; shell scripts with unset-but-`set -u`-unprotected variables; copy-pasted curl commands with the token deleted.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- No api key passed in.
- API key is required for OpenAI image variations
- API key is required for Topaz image variations
- VANTAGE_API_KEY must be provided for Vantage exports
- CohereException - {original_exception.message}
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/5a7fa4a111551a2d.
Report an issue: GitHub.