BerriAI/litellm · error · HTTPException

Failed to update cost margin config: {e}

Error message

Failed to update cost margin config: {e}

What it means

Catch-all HTTP 500 from PATCH /config/cost_margin_config: all validation passed, but the subsequent config load/save (proxy_config.get_config / save to DB) or the in-memory update (litellm.cost_margin_config = ...) raised. The original exception is logged as 'Error updating cost margin config' and embedded in the response detail so the real cause is visible.

Source

Thrown at litellm/proxy/management_endpoints/cost_tracking_settings.py:436

        # Update cost_margin_config
        config["litellm_settings"]["cost_margin_config"] = cost_margin_config

        # Save the updated config to DB
        await proxy_config.save_config(new_config=config)

        # Update in-memory litellm.cost_margin_config
        litellm.cost_margin_config = cost_margin_config

        verbose_proxy_logger.info("Updated cost_margin_config: %s", cost_margin_config)

        return {
            "message": "Cost margin configuration updated successfully",
            "status": "success",
            "values": cost_margin_config,
        }
    except Exception as e:
        verbose_proxy_logger.error("Error updating cost margin config: %s", e)
        raise HTTPException(
            status_code=500,
            detail={"error": f"Failed to update cost margin config: {e}"},
        )


@router.post(
    "/cost/estimate",
    tags=["Cost Tracking"],
    dependencies=[Depends(user_api_key_auth)],
    response_model=CostEstimateResponse,
)
async def estimate_cost(
    request: CostEstimateRequest,
    user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
) -> CostEstimateResponse:
    """
    Estimate cost for a given model and token counts.

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Read the embedded {e} text — it carries the underlying exception and points at DB vs config parsing.
  2. Restore/verify DB connectivity, then retry the PATCH (failed saves leave the old config intact).
  3. Fetch GET /config/cost_margin_config (or the raw config) to confirm state before and after retries.
  4. If corruption is indicated, repair the stored config row and re-apply.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    r = requests.patch(f"{PROXY_URL}/config/cost_margin_config", json=payload, headers=HDRS, timeout=15)
    r.raise_for_status()
except requests.HTTPError as e:
    detail = e.response.json().get("detail", {}).get("error", "")
    if e.response.status_code == 500 and "Failed to update cost margin config" in detail:
        log.error("root cause from proxy: %s", detail)
        current = requests.get(f"{PROXY_URL}/config/cost_margin_config", headers=HDRS).json()
        decide_retry_or_alert(current)  # state-aware recovery instead of blind retry
    else:
        raise

Prevention

When it happens

Trigger: Prisma write failures (DB restarted, connection pool exhausted, permissions) during save_config; corrupt existing config JSON causing merge errors; races with another concurrent config update.

Common situations: Transient DB outages at the moment of the PATCH; a config table row that was hand-edited and no longer parses; multiple operators/automation updating config simultaneously.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/c19b19518b2c0236. Report an issue: GitHub.