Skip to content

fix: close audio file handle in OpenAITools.transcribe_audio (resource leak)#8161

Merged
sannya-singal merged 5 commits into
agno-agi:mainfrom
kratos0718:fix/file-handle-leak-in-transcribe-audio
Jun 1, 2026
Merged

fix: close audio file handle in OpenAITools.transcribe_audio (resource leak)#8161
sannya-singal merged 5 commits into
agno-agi:mainfrom
kratos0718:fix/file-handle-leak-in-transcribe-audio

Conversation

@kratos0718

Copy link
Copy Markdown
Contributor

Fixes #8160

Summary

OpenAITools.transcribe_audio was opening the audio file with a bare open(audio_path, "rb") whose result was bound to a local variable and never explicitly closed. On every call — success OR failure — the file descriptor leaked. For an agent invoking transcription in a loop (batch processing, streaming audio chunks), this exhausts the process's RLIMIT_NOFILE and the next open() raises OSError: [Errno 24] Too many open files.

The fix wraps the call in a with open(...) as audio_file: block so the file is closed deterministically at the end of the API call regardless of whether audio.transcriptions.create(...) succeeds or raises.

No behavior change in the success or failure paths beyond the close — the OpenAI SDK reads the file fully during the request, so closing it right after the response is returned is safe.

Affected location

libs/agno/agno/tools/openai.py:90 — inside OpenAITools.transcribe_audio. One change: audio_file = open(audio_path, "rb")with open(audio_path, "rb") as audio_file: (and indenting the API call into the with body).

Regression test

tests/unit/tools/test_openai_tools.py::test_transcribe_audio_uses_context_manager_to_close_audio_file asserts via inspect.getsource that the function body uses with open(...) and does NOT contain the buggy audio_file = open(...) assignment pattern, so a future revert would fail in CI immediately.

Type of change

  • Bug fix

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have added tests that prove my fix works
  • My changes generate no new warnings

…rce leak)

`OpenAITools.transcribe_audio` was opening the audio file with a bare
`open(audio_path, "rb")` whose result was bound to a local variable and
never explicitly closed. On every call — success OR failure — the file
descriptor leaked. For an agent invoking transcription in a loop (e.g.
batch processing, streaming audio chunks), this exhausts the process's
`RLIMIT_NOFILE` and the next `open()` raises
`OSError: [Errno 24] Too many open files`.

The fix wraps the call in a `with open(...) as audio_file:` block so the
file is closed deterministically at the end of the API call regardless
of whether `audio.transcriptions.create(...)` succeeds or raises.

No behavior change in the success or failure paths beyond the close —
the OpenAI SDK reads the file fully during the request, so closing it
right after the response is returned is safe.

## Regression test

`tests/unit/tools/test_openai_tools.py::test_transcribe_audio_uses_context_manager_to_close_audio_file`
asserts via `inspect.getsource` that the function body uses
`with open(...)` and does NOT contain the buggy
`audio_file = open(...)` assignment pattern, so a future revert would
fail in CI immediately.
@kratos0718 kratos0718 requested a review from a team as a code owner May 29, 2026 16:14
Comment thread libs/agno/tests/unit/tools/test_openai_tools.py Outdated
Replace the source-string assertions with behavioral tests that mock the
OpenAI client and assert the audio file handle is actually closed after the
call -- on the success path, on the error path, and across repeated calls so a
descriptor leak (or a revert to a bare open()) is caught.
@kratos0718

Copy link
Copy Markdown
Contributor Author

Thanks for the review! I've rewritten the tests to validate behavior instead of matching source strings.

test_openai_tools.py now mocks the OpenAI client and asserts the audio file handle is actually closed:

  • after a successful transcription (and confirms it was still open when handed to the client),
  • after the API call raises (the worst case for the original leak), and
  • across repeated calls, so each opened handle ends up closed.

I also dropped the docstring describing the previous behavior and kept it to what the tests verify.

Comment thread libs/agno/tests/unit/tools/test_openai_tools.py Outdated
@kratos0718

Copy link
Copy Markdown
Contributor Author

Thanks! Addressed both points:

  • The tests are now behavioral — they mock the OpenAI client, capture the actual file object handed to it, and assert handle.closed is True after the call: on the success path, on the error path, and across repeated calls.
  • Removed the docstring/comment references to the previous behavior; each docstring now describes only what the test verifies.

@sannya-singal sannya-singal merged commit 3349e7e into agno-agi:main Jun 1, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] File-descriptor leak in OpenAITools.transcribe_audio — open() result never closed

2 participants