From 7d1d0517501cf4803d48670aef3ea22c5aa2d930 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/unit/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 c236032dc9f..1b0eed1ed07 100644 --- a/litellm/cost_calculator.py +++ b/litellm/cost_calculator.py @@ -1261,9 +1261,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 _extraction_usage(usage: ExtractionUsage) -> Usage: diff --git a/tests/unit/test_cost_calculator.py b/tests/unit/test_cost_calculator.py index e75bb6d3ed2..7625bb03191 100644 --- a/tests/unit/test_cost_calculator.py +++ b/tests/unit/test_cost_calculator.py @@ -1143,6 +1143,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")