{"record":{"id":"e23668ce141f1697","repo":"BerriAI/litellm","slug":"existing-credential-for-user-user-id-and-server","errorCode":null,"errorMessage":"Existing credential for user {user_id} and server {server_id} could not be verified as an OAuth2 token. Refusing to overwrite.","messagePattern":"Existing credential for user (.+?) and server (.+?) could not be verified as an OAuth2 token\\. Refusing to overwrite\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/_experimental/mcp_server/db.py","lineNumber":1423,"sourceCode":"    }\n    if refresh_token:\n        payload[\"refresh_token\"] = refresh_token\n    if expires_at:\n        payload[\"expires_at\"] = expires_at\n    if scopes:\n        payload[\"scopes\"] = scopes\n\n    # Guard against silently overwriting a BYOK credential with an OAuth token.\n    # Skip the guard when the caller knows the row is already an OAuth2 credential\n    # (e.g. during token refresh), saving an extra DB round-trip.\n    if not skip_byok_guard:\n        existing: Final = await _db_find_user_credential_row(prisma_client, user_id, server_id)\n        if existing is not None and _decode_oauth_payload(existing.credential_b64) is None:\n            # Existing row is either a BYOK secret or an OAuth2 row that no\n            # longer decrypts (e.g. after a salt-key rotation).  In either\n            # case, refuse to overwrite — the caller would clobber data\n            # that may still be recoverable.\n            raise ValueError(\n                f\"Existing credential for user {user_id} and server \"\n                f\"{server_id} could not be verified as an OAuth2 token. \"\n                f\"Refusing to overwrite.\"\n            )\n\n    encoded: Final = encrypt_value_helper(json.dumps(payload))\n    await _db_upsert_user_credential_row(prisma_client, user_id, server_id, encoded)\n\n\ndef is_oauth_credential_expired(cred: OAuthCredentialPayload, buffer_seconds: int = 0) -> bool:\n    \"\"\"Return True if the OAuth2 credential's access_token has expired.\n\n    Checks the ``expires_at`` ISO-format string stored in the credential payload.\n    Returns False when ``expires_at`` is absent or unparseable (treat as non-expired).\n    With ``buffer_seconds`` > 0, a token that is still valid but expires within the\n    buffer is also treated as expired, so callers can refresh proactively instead of\n    handing back a token that may lapse mid-request.\n    \"\"\"","sourceCodeStart":1405,"sourceCodeEnd":1441,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/_experimental/mcp_server/db.py#L1405-L1441","documentation":"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.","triggerScenarios":"Thrown at litellm/proxy/_experimental/mcp_server/db.py:1423 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","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."],"exampleFix":"Remove the stale credential row, then re-authorize.","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}