[GH-ISSUE #21411] bug: File descriptor leak in audio.py and pipelines.py — open() without close #19468

Closed
opened 2026-04-20 01:56:31 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @ashm-dev on GitHub (Feb 14, 2026).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/21411

Description

File handles opened with open(file_path, "rb") are passed to HTTP requests but never closed. Each request leaks one file descriptor.

Locations

1. audio.py (line ~645)

File: backend/open_webui/routers/audio.py

r = requests.post(
    url=f"{request.app.state.config.STT_OPENAI_API_BASE_URL}/audio/transcriptions",
    headers=headers,
    files={"file": (filename, open(file_path, "rb"))},  # never closed
    data=payload,
)

requests.post does not close file objects passed in files. If the request fails or the function returns early, the file descriptor leaks.

2. pipelines.py (line ~234)

File: backend/open_webui/routers/pipelines.py

form_data = aiohttp.FormData()
form_data.add_field(
    "file",
    open(file_path, "rb"),  # never closed
    filename=filename,
    content_type="application/octet-stream",
)

Same issue with aiohttp.FormData.

Fix

Simplest fix — use pathlib.Path.read_bytes(), which opens, reads, and closes the file in one call:

from pathlib import Path

# audio.py
r = requests.post(
    url=...,
    files={"file": (filename, Path(file_path).read_bytes())},
    data=payload,
)

# pipelines.py
form_data = aiohttp.FormData()
form_data.add_field(
    "file",
    Path(file_path).read_bytes(),
    filename=filename,
    content_type="application/octet-stream",
)

No file descriptor leak — read_bytes() handles open/close internally.

Originally created by @ashm-dev on GitHub (Feb 14, 2026). Original GitHub issue: https://github.com/open-webui/open-webui/issues/21411 ## Description File handles opened with `open(file_path, "rb")` are passed to HTTP requests but never closed. Each request leaks one file descriptor. ## Locations ### 1. audio.py (line ~645) **File:** `backend/open_webui/routers/audio.py` ```python r = requests.post( url=f"{request.app.state.config.STT_OPENAI_API_BASE_URL}/audio/transcriptions", headers=headers, files={"file": (filename, open(file_path, "rb"))}, # never closed data=payload, ) ``` `requests.post` does not close file objects passed in `files`. If the request fails or the function returns early, the file descriptor leaks. ### 2. pipelines.py (line ~234) **File:** `backend/open_webui/routers/pipelines.py` ```python form_data = aiohttp.FormData() form_data.add_field( "file", open(file_path, "rb"), # never closed filename=filename, content_type="application/octet-stream", ) ``` Same issue with `aiohttp.FormData`. ## Fix Simplest fix — use `pathlib.Path.read_bytes()`, which opens, reads, and closes the file in one call: ```python from pathlib import Path # audio.py r = requests.post( url=..., files={"file": (filename, Path(file_path).read_bytes())}, data=payload, ) # pipelines.py form_data = aiohttp.FormData() form_data.add_field( "file", Path(file_path).read_bytes(), filename=filename, content_type="application/octet-stream", ) ``` No file descriptor leak — `read_bytes()` handles open/close internally.
Author
Owner

@tjbck commented on GitHub (Feb 15, 2026):

Addressed in dev!

<!-- gh-comment-id:3905564973 --> @tjbck commented on GitHub (Feb 15, 2026): Addressed in dev!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#19468