From 6a3c36fcc344d4848d72bef0809741b2e4b7bd80 Mon Sep 17 00:00:00 2001 From: Emerson Gomes Date: Wed, 23 Sep 2026 04:49:54 -0500 Subject: [PATCH] fix(transcription): reject nonfinite provider durations --- litellm/cost_calculator.py | 4 +--- tests/test_litellm/test_cost_calculator.py | 9 +++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/litellm/cost_calculator.py b/litellm/cost_calculator.py index 951e336b766..87a5c6c867d 100644 --- a/litellm/cost_calculator.py +++ b/litellm/cost_calculator.py @@ -1038,9 +1038,7 @@ def _get_transcription_usage_duration(completion_response: object) -> float | No seconds: Final = ( usage_object.get("seconds") if isinstance(usage_object, dict) else getattr(usage_object, "seconds", None) ) - if isinstance(seconds, bool) or not isinstance(seconds, (int, float)) or seconds < 0: - return None - return float(seconds) + return normalized_audio_duration_seconds(seconds) def _is_known_usage_objects(usage_obj): diff --git a/tests/test_litellm/test_cost_calculator.py b/tests/test_litellm/test_cost_calculator.py index cf2e43a2540..45423c78b21 100644 --- a/tests/test_litellm/test_cost_calculator.py +++ b/tests/test_litellm/test_cost_calculator.py @@ -334,6 +334,15 @@ def test_transcription_usage_cost_returns_zero_for_unknown_type(): assert _transcription_usage_cost({}, {}) == 0.0 +@pytest.mark.parametrize("malformed_seconds", [-1.0, float("nan"), float("inf"), 10**1000, True]) +def test_transcription_ignores_invalid_provider_duration(malformed_seconds: float | int | bool) -> None: + from litellm.cost_calculator import _get_transcription_usage_duration + + response: Final = SimpleNamespace(usage={"type": "duration", "seconds": malformed_seconds}) + + assert _get_transcription_usage_duration(response) is None + + def test_get_transcription_model_falls_back_to_session_model(monkeypatch): """session.model is used when transcription-specific model fields are absent.""" monkeypatch.setenv("LITELLM_LOCAL_MODEL_COST_MAP", "True")