BerriAI/litellm · error · ValueError
Existing credential for user {user_id} and server {server_id
Error message
Existing credential for user {user_id} and server {server_id} could not be verified as an OAuth2 token. Refusing to overwrite. What it means
Raised by the MCP credential store when saving an OAuth token over an existing user credential that does not decode as an OAuth2 payload (i.e. a BYOK API key). It refuses the overwrite to avoid silently destroying a user-entered key; the skip guard exists for known-refresh paths.
Source
Thrown at litellm/proxy/_experimental/mcp_server/db.py:1423
}
if refresh_token:
payload["refresh_token"] = refresh_token
if expires_at:
payload["expires_at"] = expires_at
if scopes:
payload["scopes"] = scopes
# Guard against silently overwriting a BYOK credential with an OAuth token.
# Skip the guard when the caller knows the row is already an OAuth2 credential
# (e.g. during token refresh), saving an extra DB round-trip.
if not skip_byok_guard:
existing: Final = await _db_find_user_credential_row(prisma_client, user_id, server_id)
if existing is not None and _decode_oauth_payload(existing.credential_b64) is None:
# Existing row is either a BYOK secret or an OAuth2 row that no
# longer decrypts (e.g. after a salt-key rotation). In either
# case, refuse to overwrite — the caller would clobber data
# that may still be recoverable.
raise ValueError(
f"Existing credential for user {user_id} and server "
f"{server_id} could not be verified as an OAuth2 token. "
f"Refusing to overwrite."
)
encoded: Final = encrypt_value_helper(json.dumps(payload))
await _db_upsert_user_credential_row(prisma_client, user_id, server_id, encoded)
def is_oauth_credential_expired(cred: OAuthCredentialPayload, buffer_seconds: int = 0) -> bool:
"""Return True if the OAuth2 credential's access_token has expired.
Checks the ``expires_at`` ISO-format string stored in the credential payload.
Returns False when ``expires_at`` is absent or unparseable (treat as non-expired).
With ``buffer_seconds`` > 0, a token that is still valid but expires within the
buffer is also treated as expired, so callers can refresh proactively instead of
handing back a token that may lapse mid-request.
"""View on GitHub (pinned to 77b7c6c40c)
Solutions
- Delete the existing stored credential for that user/server, then re-run the OAuth flow.
- Or verify/fix the stored token so it parses as OAuth2.
Example fix
Remove the stale credential row, then re-authorize.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at litellm/proxy/_experimental/mcp_server/db.py:1423 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/e23668ce141f1697.
Report an issue: GitHub.