From 8345d352782d8c89defefc62c59dad91b1e462f0 Mon Sep 17 00:00:00 2001 From: Charan Rathore Date: Mon, 28 Sep 2026 09:37:49 +0530 Subject: [PATCH 1/3] fix: close audio health-check file after transcription --- .../health_check_helpers.py | 12 +++++--- .../test_health_check_helpers.py | 30 +++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/litellm/litellm_core_utils/health_check_helpers.py b/litellm/litellm_core_utils/health_check_helpers.py index a0f027cd58f..d77463e9435 100644 --- a/litellm/litellm_core_utils/health_check_helpers.py +++ b/litellm/litellm_core_utils/health_check_helpers.py @@ -193,6 +193,13 @@ class HealthCheckHelpers: from litellm.litellm_core_utils.health_check_utils import _filter_model_params from litellm.realtime_api.main import _realtime_health_check + async def audio_transcription_health_check(): + with get_audio_file_for_health_check() as audio_file: + return await litellm.atranscription( + **_filter_model_params(model_params=model_params), + file=audio_file, + ) + return { "chat": lambda: litellm.acompletion( **model_params, @@ -212,10 +219,7 @@ class HealthCheckHelpers: }, input=prompt or "test", ), - "audio_transcription": lambda: litellm.atranscription( - **_filter_model_params(model_params=model_params), - file=get_audio_file_for_health_check(), - ), + "audio_transcription": audio_transcription_health_check, "image_generation": lambda: litellm.aimage_generation( **_filter_model_params(model_params=model_params), prompt=prompt, diff --git a/tests/unit/litellm_core_utils/test_health_check_helpers.py b/tests/unit/litellm_core_utils/test_health_check_helpers.py index 47c4576f91f..8870a5bd9f7 100644 --- a/tests/unit/litellm_core_utils/test_health_check_helpers.py +++ b/tests/unit/litellm_core_utils/test_health_check_helpers.py @@ -37,6 +37,36 @@ def _distinct_rgb_colors(png: bytes) -> set[bytes]: return {bytes(row[i : i + 3]) for row in rows for i in range(1, row_size, 3)} +@pytest.mark.asyncio +@pytest.mark.parametrize("raises", [False, True]) +async def test_audio_transcription_health_check_closes_file(raises: bool): + file_handles = [] + + async def transcription(**kwargs): + file = kwargs["file"] + file_handles.append(file) + assert not file.closed + assert file.read(4) == b"RIFF" + if raises: + raise RuntimeError("transcription failed") + return {"text": "healthy"} + + handlers = HealthCheckHelpers.get_mode_handlers( + model="whisper-1", + custom_llm_provider="openai", + model_params={"model": "openai/whisper-1", "api_key": "sk-test"}, + ) + with patch("litellm.atranscription", side_effect=transcription): + if raises: + with pytest.raises(RuntimeError, match="transcription failed"): + await handlers["audio_transcription"]() + else: + assert await handlers["audio_transcription"]() == {"text": "healthy"} + + assert len(file_handles) == 1 + assert file_handles[0].closed + + @pytest.mark.asyncio async def test_image_edit_health_check_handler_uses_descriptive_prompt_and_multicolor_png(): model_params = {"model": "openai/gpt-image-1", "api_key": "sk-test"} From db16d964c9437a58b4b6cad1f6b8c70499c6e6d3 Mon Sep 17 00:00:00 2001 From: Charan Rathore Date: Mon, 28 Sep 2026 09:42:31 +0530 Subject: [PATCH 2/3] test: capture audio handle through mock call --- .../unit/litellm_core_utils/test_health_check_helpers.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/unit/litellm_core_utils/test_health_check_helpers.py b/tests/unit/litellm_core_utils/test_health_check_helpers.py index 8870a5bd9f7..6e7e54c60e6 100644 --- a/tests/unit/litellm_core_utils/test_health_check_helpers.py +++ b/tests/unit/litellm_core_utils/test_health_check_helpers.py @@ -40,11 +40,8 @@ def _distinct_rgb_colors(png: bytes) -> set[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("raises", [False, True]) async def test_audio_transcription_health_check_closes_file(raises: bool): - file_handles = [] - async def transcription(**kwargs): file = kwargs["file"] - file_handles.append(file) assert not file.closed assert file.read(4) == b"RIFF" if raises: @@ -56,15 +53,15 @@ async def test_audio_transcription_health_check_closes_file(raises: bool): custom_llm_provider="openai", model_params={"model": "openai/whisper-1", "api_key": "sk-test"}, ) - with patch("litellm.atranscription", side_effect=transcription): + with patch("litellm.atranscription", side_effect=transcription) as mock_transcription: if raises: with pytest.raises(RuntimeError, match="transcription failed"): await handlers["audio_transcription"]() else: assert await handlers["audio_transcription"]() == {"text": "healthy"} - assert len(file_handles) == 1 - assert file_handles[0].closed + mock_transcription.assert_called_once() + assert mock_transcription.call_args.kwargs["file"].closed @pytest.mark.asyncio From a82dc87519f27c431abaf37152e68cf2b1dc9006 Mon Sep 17 00:00:00 2001 From: Charan Rathore Date: Mon, 28 Sep 2026 10:06:25 +0530 Subject: [PATCH 3/3] fix: type audio health-check file as binary handle --- litellm/litellm_core_utils/audio_utils/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litellm/litellm_core_utils/audio_utils/utils.py b/litellm/litellm_core_utils/audio_utils/utils.py index dab3e48f91a..74cdb2cefa6 100644 --- a/litellm/litellm_core_utils/audio_utils/utils.py +++ b/litellm/litellm_core_utils/audio_utils/utils.py @@ -5,7 +5,7 @@ Utils used for litellm.transcription() and litellm.atranscription() import hashlib import os from dataclasses import dataclass -from typing import Final +from typing import BinaryIO, Final from litellm.types.files import ( AUDIO_FILE_TYPES, @@ -244,7 +244,7 @@ def get_audio_file_content_hash(file_obj: FileTypes) -> str: return hash_object.hexdigest() -def get_audio_file_for_health_check() -> FileTypes: +def get_audio_file_for_health_check() -> BinaryIO: """ Get an audio file for health check