BerriAI/litellm · error · Exception
Error updating key: {response_text}
Error message
Error updating key: {response_text} What it means
KeysManagementClient.update() wraps every failure of POST {base_url}/key/update in a bare Exception whose message is 'Error updating key: ' + the raw response body — or the literal 'Error updating key: None' when no response exists (connection refused, DNS failure, timeout). Unlike its sibling methods it catches Exception rather than HTTPError, so all type information is lost: a 401 that would elsewhere become UnauthorizedError surfaces here as this generic exception, and the original traceback is discarded because the raise uses no `from`. To diagnose, you must read the server text embedded in the message.
Source
Thrown at litellm/proxy/client/keys.py:287
data["team_id"] = team_id
if models is not None:
data["models"] = models
if spend is not None:
data["spend"] = spend
if duration is not None:
data["duration"] = duration
if aliases is not None:
data["aliases"] = aliases
request: Final = requests.Request("POST", url, headers=self._get_headers(), json=data)
session: Final = requests.Session()
response_text: str | None = None
try:
response: Final = session.send(request.prepare())
response_text = response.text
response.raise_for_status()
return response.json()
except Exception:
raise Exception(f"Error updating key: {response_text}")
def info(self, key: str, return_request: bool = False) -> dict[str, Any] | requests.Request:
"""
Get information about API keys.
Args:
key (str): The key hash to get information about
return_request (bool): If True, returns the prepared request object instead of executing it
Returns:
Union[Dict[str, Any], requests.Request]: Either the response from the server or a prepared request object if return_request is True
Raises:
UnauthorizedError: If the request fails with a 401 status code
requests.exceptions.RequestException: If the request fails with any other error
"""
url: Final = f"{self._base_url}/key/info?key={key}"
request: Final = requests.Request("GET", url, headers=self._get_headers())View on GitHub (pinned to 77b7c6c40c)
Solutions
- Read the text after the prefix — the proxy's actual error (e.g.{"error":"Key does not exist in proxy"}) tells you whether it's auth, missing key, or validation
- Pre-verify the key with keys.info(key=...) (which raises typed UnauthorizedError/HTTPError) and confirm you pass the key hash, not the alias
- If the message ends with 'None', the request never got a response: check the proxy is running and base_url/port are correct
- Catch this Exception narrowly around update() and re-raise a typed error, since the library discards the original
Example fix
# before
keys.update(key="sk-123", spend=100) # Exception: Error updating key: {"error": "Key does not exist in proxy"}
# after
from litellm.proxy.client.exceptions import UnauthorizedError
try:
keys.info(key="sk-123") # typed pre-check: raises UnauthorizedError on bad creds
keys.update(key="sk-123", spend=100)
except Exception as e:
raise RuntimeError(f"key update failed: {e}") from e Defensive patterns
Strategy: validation
Validate before calling
from litellm.proxy.client.keys import KeysManagementClient
def update_key_if_exists(keys: KeysManagementClient, key: str, **fields) -> dict:
keys.info(key=key) # typed pre-check: raises UnauthorizedError for bad creds, HTTPError 404 if gone
return keys.update(key=key, **fields) Try / catch
try:
keys.update(key=key, spend=new_spend)
except Exception as e: # update() raises a bare Exception — cannot narrow further
msg = str(e)
if msg.endswith("None"):
raise RuntimeError("proxy unreachable (no HTTP response)") from e
raise RuntimeError(f"key update rejected by proxy: {msg}") from e Prevention
- Always pre-verify the key with keys.info() — it raises typed errors — before calling update()
- Pass the key hash (sk-...), not the alias, to /key/update
- Remember update() collapses ALL failures (including 401 and network errors) into one generic Exception; code around it accordingly
When it happens
Trigger: Updating a key hash that no longer exists (400/404 body inline in the message); proxy unreachable or base_url wrong ('Error updating key: None'); auth rejected (401 body inline); server rejecting duration/spend/models values (400/422 body inline); passing a key alias where the hash is expected.
Common situations: Key deleted on the proxy between fetch and update; network flake or wrong port in base_url; rotated admin key; scripts assuming typed exceptions (UnauthorizedError) around update() and missing this generic one.
Related errors
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/4eed85e691d9af0f.
Report an issue: GitHub.