{"record":{"id":"2a17b241a7a42aa7","repo":"BerriAI/litellm","slug":"byok-auth-unavailable","errorCode":"byok_auth_unavailable","errorMessage":"BYOK credential check requires a database connection.","messagePattern":"BYOK credential check requires a database connection\\.","errorType":"http","errorClass":"HTTPException","httpStatus":503,"severity":"error","filePath":"litellm/proxy/_experimental/mcp_server/server.py","lineNumber":2596,"sourceCode":"                            \"message\": (\n                                \"No stored credential found for this BYOK server. \"\n                                \"Complete the OAuth authorization flow to provide your API key.\"\n                            ),\n                        },\n                        headers={\n                            \"WWW-Authenticate\": 'Bearer resource_metadata=\"/.well-known/oauth-protected-resource\"'\n                        },\n                    )\n                return\n\n        from litellm.proxy._experimental.mcp_server.db import get_user_credential\n        from litellm.proxy.proxy_server import prisma_client\n\n        if prisma_client is None:\n            # Fail closed on DB unavailability: returning here previously\n            # bypassed the ownership check and let any proxy-authenticated\n            # caller invoke BYOK tools during outage windows.\n            raise HTTPException(\n                status_code=503,\n                detail={\n                    \"error\": \"byok_auth_unavailable\",\n                    \"server_id\": mcp_server.server_id,\n                    \"server_name\": mcp_server.server_name or mcp_server.name,\n                    \"message\": \"BYOK credential check requires a database connection.\",\n                },\n            )\n\n        credential: Final = await get_user_credential(\n            prisma_client=prisma_client,\n            user_id=user_id,\n            server_id=mcp_server.server_id,\n        )\n        _write_byok_cred_cache(user_id, mcp_server.server_id, credential)\n        if credential is None:\n            raise HTTPException(\n                status_code=401,","sourceCodeStart":2578,"sourceCodeEnd":2614,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/_experimental/mcp_server/server.py#L2578-L2614","documentation":"BYOK servers keep credentials in the database, so the pre-dispatch ownership check needs prisma_client. When the proxy runs without a database, LiteLLM fails closed: HTTP 503 with error code byok_auth_unavailable instead of skipping the check. The source comment records why — the old early-return silently let any proxy-authenticated caller use BYOK tools during DB outage windows.","triggerScenarios":"The proxy starts without DATABASE_URL (or the DB is still initializing) while a called MCP server has is_byok set; a DB outage mid-session causes the same failure on later calls.","commonSituations":"Dev/docker-compose setups running config.yaml without Postgres; promoting a config from an environment that had a DB into one that does not; migration windows.","solutions":["Set DATABASE_URL, run prisma migrations, and restart the proxy so prisma_client initializes.","If this deployment genuinely has no DB, remove BYOK servers from its config and use static server credentials.","Treat the 503 as a health signal: check DB connectivity first; the call succeeds once the DB is reachable."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"async def db_ready(client: httpx.AsyncClient) -> bool:\n    r = await client.get(f\"{base}/health/liveliness\")\n    return r.status_code == 200  # only meaningful when DATABASE_URL is configured at all","typeGuard":null,"tryCatchPattern":"except httpx.HTTPStatusError as e:\n    d = e.response.json().get(\"detail\", {})\n    if e.response.status_code == 503 and isinstance(d, dict) and d.get(\"error\") == \"byok_auth_unavailable\":\n        # DB is down or not configured: wait for DB health, then retry;\n        # if DATABASE_URL was never set, fix config instead of retrying\n        await wait_for_database_then_retry(payload)\n        return\n    raise","preventionTips":["Always set DATABASE_URL in any deployment that registers BYOK MCP servers.","Include a DB health gate in startup probes so traffic only flows when prisma_client is initialized."],"tags":["mcp","byok","database","http-503","availability"],"backgroundTag":"database-not-configured","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}