From 10f4e42605848fca83cb1803a278a23ebd15df63 Mon Sep 17 00:00:00 2001 From: yassin Date: Thu, 27 Aug 2026 02:48:43 +0000 Subject: [PATCH] fix(alerting): reject non-finite values in user spend alert settings Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/types/integrations/slack_alerting.py | 4 ++++ .../SlackAlerting/test_user_spend_alerts.py | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/litellm/types/integrations/slack_alerting.py b/litellm/types/integrations/slack_alerting.py index 51eb5c8190e..64c0c530e9b 100644 --- a/litellm/types/integrations/slack_alerting.py +++ b/litellm/types/integrations/slack_alerting.py @@ -94,16 +94,19 @@ class SlackAlertingArgs(LiteLLMPydanticObjectBase): daily_spend_per_user_threshold: float | None = Field( default=None, gt=0, + allow_inf_nan=False, description="Alert when a user's spend for the current day (UTC) crosses this USD amount. Off by default.", ) monthly_spend_per_user_threshold: float | None = Field( default=None, gt=0, + allow_inf_nan=False, description="Alert when a user's spend for the current calendar month (UTC) crosses this USD amount. Off by default.", ) spend_anomaly_multiplier: float = Field( default=3.0, gt=0, + allow_inf_nan=False, description="Flag a user's spend as anomalous when today's spend exceeds this multiple of their trailing daily average.", ) spend_anomaly_baseline_days: int = Field( @@ -114,6 +117,7 @@ class SlackAlertingArgs(LiteLLMPydanticObjectBase): spend_anomaly_min_spend: float = Field( default=10.0, gt=0, + allow_inf_nan=False, description="Minimum spend (USD) a user must reach today before an anomaly alert can fire. Reduces false positives.", ) user_spend_check_interval: int = Field( diff --git a/tests/test_litellm/integrations/SlackAlerting/test_user_spend_alerts.py b/tests/test_litellm/integrations/SlackAlerting/test_user_spend_alerts.py index 28f5d0bf7a2..45e1acecec8 100644 --- a/tests/test_litellm/integrations/SlackAlerting/test_user_spend_alerts.py +++ b/tests/test_litellm/integrations/SlackAlerting/test_user_spend_alerts.py @@ -85,7 +85,7 @@ def test_anomaly_detected_above_multiple_of_baseline(): ) assert [e.kind for e in events] == ["anomaly"] assert events[0].alert_type == AlertType.user_spend_anomalies - assert "`$10.00`" in events[0].message # baseline daily average + assert "`$10.00`" in events[0].message assert events[0].cache_key == "user_spend_alert_anomaly_user-1_2026-08-15" @@ -129,6 +129,17 @@ def test_invalid_config_rejected(): SlackAlertingArgs(user_spend_check_interval=10) +def test_non_finite_config_rejected(): + with pytest.raises(ValidationError, match="daily_spend_per_user_threshold"): + SlackAlertingArgs(daily_spend_per_user_threshold=float("inf")) + with pytest.raises(ValidationError, match="spend_anomaly_multiplier"): + SlackAlertingArgs(spend_anomaly_multiplier=float("nan")) + with pytest.raises(ValidationError, match="spend_anomaly_min_spend"): + SlackAlertingArgs(spend_anomaly_min_spend=float("inf")) + with pytest.raises(ValidationError, match="user_spend_check_interval"): + SlackAlertingArgs(user_spend_check_interval=float("inf")) + + def test_anomalies_disabled_suppresses_anomaly_events(): args: Final = SlackAlertingArgs(spend_anomaly_multiplier=3.0, spend_anomaly_min_spend=10.0) assert _evaluate(_row(daily_spend=500.0, monthly_spend=500.0), args, anomalies=False) == ()