BerriAI/litellm · error · HTTPException

Error saving email settings to general_settings: {str(e)}

Error message

Error saving email settings to general_settings: {str(e)}

What it means

Raised as HTTPException 500 by the enterprise email-settings endpoint (set/update email event settings) when persisting the merged general_settings to the database fails — most commonly at the prisma_client.db.litellm_config.upsert for param_name='general_settings'. The underlying exception string is included in the detail.

Source

Thrown at enterprise/litellm_enterprise/enterprise_callbacks/send_emails/endpoints.py:103

        # Update email_settings in general_settings
        general_settings["email_settings"] = settings

        # Convert to JSON for storage
        json_settings = json.dumps(general_settings, default=str)

        # Save updated general settings
        await prisma_client.db.litellm_config.upsert(
            where={"param_name": "general_settings"},
            data={
                "create": {
                    "param_name": "general_settings",
                    "param_value": json_settings,
                },
                "update": {"param_value": json_settings},
            },
        )
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"Error saving email settings to general_settings: {str(e)}",
        )


@router.get(
    "/email/event_settings",
    response_model=EmailEventSettingsResponse,
    tags=["email management"],
    dependencies=[Depends(user_api_key_auth)],
)
async def get_email_event_settings(
    user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
):
    """
    Get all email event settings
    """
    from litellm.proxy.proxy_server import prisma_client

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Read {str(e)} in the response detail — it usually names the Prisma error (P1001 connection, P2021 table missing, unique constraint).
  2. Verify DB connectivity and that schema migrations ran (the LiteLLM_Config table exists).
  3. Retry the request once transient DB issues are resolved; the upsert is idempotent.
  4. If serialization is the cause, remove non-serializable values from general_settings and re-save.
Defensive patterns

Strategy: retry

Validate before calling

import httpx

# preflight: DB reachable and litellm_config table present
r = httpx.get(f"{PROXY_BASE}/health/liveliness", timeout=5)
assert r.status_code == 200, "proxy/db unhealthy — email settings save will fail"

Try / catch

for attempt in range(2):
    try:
        resp = await client.post("/email/event_settings", json=settings)
        break
    except HTTPException as e:
        if e.status_code == 500 and "Error saving email settings" in str(e.detail):
            await asyncio.sleep(2)  # transient DB issue — one retry (upsert is idempotent)
            continue
        raise

Prevention

When it happens

Trigger: Calling the email settings PUT/POST endpoint while the Prisma database is unreachable, the LiteLLM_Config table does not exist (migrations not run), json_settings fails to serialize, or the upsert violates a DB constraint. Any exception in the try block becomes this 500.

Common situations: Proxy started without DB migrations (prisma generate/migrate) so litellm_config table is missing; DB credentials wrong or DB restarted mid-request; concurrent writes to general_settings causing serialization issues; non-JSON-serializable values in the merged settings dict.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/3ccf83752bfffdc8. Report an issue: GitHub.