BerriAI/litellm · critical · Exception
Connect Proxy to database to generate keys -…
Error message
Connect Proxy to database to generate keys - https://docs.litellm.ai/docs/proxy/virtual-keys
What it means
generate_key_helper_fn is the core behind POST /key/generate and /user/new; virtual keys are DB records, so it immediately raises this Exception when prisma_client is None. If you see it, the proxy has no database attached, making all key generation impossible (the UI's 'Create Key' button fails the same way).
Solutions
- Set DATABASE_URL to a Postgres connection string (or add database_connection.url in the config) and restart the proxy.
- Verify the DB is reachable from the proxy and Prisma migrations applied (proxy logs 'Prisma DB Connected' on startup).
- Add a startup/health assertion on DB connectivity in your deployment before enabling key issuance.
Example fix
# before
# no database configured
client.post("/key/generate", json={"models": ["gpt-4o"]})
# after
export DATABASE_URL="postgresql://user:pass@db:5432/litellm"
# restart proxy, then:
client.post("/key/generate", json={"models": ["gpt-4o"]}) Defensive patterns
Strategy: validation
Validate before calling
if not os.environ.get("DATABASE_URL"):
raise RuntimeError("key generation requires a Postgres DB: set DATABASE_URL before starting litellm")
key = client.post("/key/generate", json={"models": ["gpt-4o"]}).json() Try / catch
try:
key = client.post("/key/generate", json={"models": ["gpt-4o"]})
key.raise_for_status()
except HTTPError as e:
if "Connect Proxy to database" in e.response.text:
raise RuntimeError("litellm has no DB attached; provisioning blocked") from e
raise Prevention
- Make a Postgres database a hard prerequisite in every environment that issues virtual keys.
- Fail deployments fast: assert DB connectivity (and 'Prisma DB Connected' in logs) before enabling the UI/API.
- Keep DB migrations and DATABASE_URL in infrastructure-as-code so restarts and redeploys stay consistent.
When it happens
Trigger: POST /key/generate (or any flow that creates a key, including SSO user auto-provisioning) on a proxy started without DATABASE_URL / database config; DB env var lost in a container restart or redeploy.
Common situations: Fresh local install without Postgres; UI enabled but DB never wired; DATABASE_URL present in shell but proxy run under systemd/k8s with a sanitized env; migration to a new orchestrator dropped the secret.
Related errors
- Database not connected. Connect a database to your proxy -…
- No db connected
- No DB Connected. See -…
- Custom code guardrail requires a guardrail_name
- Custom code guardrail requires 'custom_code' in…
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/e49d74f163896fdf.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/proxy/management_endpoints/key_management_endpoints.py:3805
table_name: Literal["key", "user"] | None = None,
send_invite_email: bool | None = None,
created_by: str | None = None,
updated_by: str | None = None,
allowed_routes: list | None = None,
key_type: str | None = None,
sso_user_id: str | None = None,
object_permission_id: str | None = None, # object_permission_id <-> LiteLLM_ObjectPermissionTable
object_permission: LiteLLM_ObjectPermissionBase | None = None,
auto_rotate: bool | None = None,
rotation_interval: str | None = None,
router_settings: dict | None = None,
access_group_ids: list[str] | None = None,
budget_limits: list | None = None, # multiple concurrent budget windows
):
from litellm.proxy.proxy_server import premium_user, prisma_client
if prisma_client is None:
raise Exception("Connect Proxy to database to generate keys - https://docs.litellm.ai/docs/proxy/virtual_keys ")
if token is None:
if key is not None:
token = key
else:
token = f"sk-{secrets.token_urlsafe(LENGTH_OF_LITELLM_GENERATED_KEY)}"
if duration is None: # allow tokens that never expire
expires = None
else:
# Add duration to current time for exact expiration (not standardized reset time)
duration_seconds: Final = duration_in_seconds(duration)
expires = datetime.now(timezone.utc) + timedelta(seconds=duration_seconds)
if key_budget_duration is None: # one-time budget
key_reset_at = None
else:
key_reset_at = get_budget_reset_time(budget_duration=key_budget_duration)View on GitHub (pinned to 77b7c6c40c)