BerriAI/litellm · error · ProxyException
internal_server_error
internal_server_error
Error message
Failed to delete keys got None response from delete_verification_token
What it means
After dispatching the actual deletion, /key/delete asserts the delete helper returned a count; if delete_verification_tokens / alias deletion returned None it raises this ProxyException typed internal_server_error with HTTP 500. A None (as opposed to 0) return is an internal contract violation — typically the delete helper silently swallowed a DB error — not a caller mistake.
Source
Thrown at litellm/proxy/management_endpoints/key_management_endpoints.py:3423
litellm_changed_by=litellm_changed_by,
)
num_keys_to_be_deleted = len(data.keys)
deleted_keys = data.keys
elif data.key_aliases:
number_deleted_keys, _keys_being_deleted = await delete_key_aliases(
key_aliases=data.key_aliases,
prisma_client=prisma_client,
user_api_key_cache=user_api_key_cache,
user_api_key_dict=user_api_key_dict,
litellm_changed_by=litellm_changed_by,
)
num_keys_to_be_deleted = len(data.key_aliases)
deleted_keys = data.key_aliases
else:
raise ValueError("Invalid request type")
if number_deleted_keys is None:
raise ProxyException(
message="Failed to delete keys got None response from delete_verification_token",
type=ProxyErrorTypes.internal_server_error,
param="keys",
code=status.HTTP_500_INTERNAL_SERVER_ERROR,
)
verbose_proxy_logger.debug("/key/delete - deleted_keys=%s", number_deleted_keys)
try:
assert num_keys_to_be_deleted == len(deleted_keys)
except Exception:
raise HTTPException(
status_code=400,
detail={
"error": f"Not all keys passed in were deleted. This probably means you don't have access to delete all the keys passed in. Keys passed in={num_keys_to_be_deleted}, Deleted keys ={number_deleted_keys}"
},
)
verbose_proxy_logger.debug(View on GitHub (pinned to 77b7c6c40c)
Solutions
- Retry the request once — if it was a transient DB blip the second attempt usually succeeds (verify keys still exist first).
- Check proxy logs for the underlying Prisma/DB exception just before this error; fix that (connectivity, migrations, prisma schema).
- If reproducible on current version, open a LiteLLM GitHub issue including the log trace and request shape.
Defensive patterns
Strategy: retry
Try / catch
for attempt in range(2):
resp = client.post("/key/delete", json={"keys": keys})
if resp.status_code == 500 and "None response" in resp.text:
continue # one retry for transient DB failure
resp.raise_for_status()
break
else:
alert("/key/delete returning None from delete_verification_token — check proxy logs") Prevention
- Keep proxy and database logs correlated so the underlying Prisma error for these 500s is findable.
- Stabilize DB connectivity (pool sizing, timeouts) to avoid mid-request drops during deletes.
- Pin LiteLLM versions in production; this class of contract break usually appears across upgrades.
When it happens
Trigger: POST /key/delete while the database connection drops mid-request; a Prisma error during delete_many being caught and converted to a None result; certain upgrades where the repository delete method's return contract changed.
Common situations: Transient DB failover or connection pool exhaustion exactly when the delete ran; Prisma binary/schema mismatch after an upgrade; very rarely a bug — report it with the stack trace if persistent.
Related errors
- Error fetching cache settings: {e}
- Failed to fetch analytics: {e}
- Failed to update cost discount config: {e}
- Failed to update cost margin config: {e}
- Database not connected. Connect a database to your proxy - h
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/c7bbe52c60504878.
Report an issue: GitHub.