Location
apps/backend/app/routers/reports.py:129-132
Description
The download_pdf endpoint creates a temporary PDF file with tempfile.NamedTemporaryFile(delete=False) and returns it via FileResponse. However, the file is never deleted after the response is sent. On a long-running server, each PDF generation leaks a temp file, accumulating disk usage over time.
Reproduction (on main branch)
Buggy Code
# apps/backend/app/routers/reports.py:129-132
@report_router.post("/report-pdf")
async def download_pdf(report_data: dict):
html_content = render_report_html(report_data["report_data"])
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
HTML(string=html_content).write_pdf(tmp.name)
tmp_path = tmp.name
return FileResponse(tmp_path, media_type="application/pdf", filename="report.pdf")
# ^^^ tmp_path is NEVER deleted — file leaks on every request
Reproduction Script (reproduce_bug.py)
import inspect, os
reports_path = "apps/backend/app/routers/reports.py"
with open(reports_path, 'r') as f:
source = f.read()
func_start = source.find("async def download_pdf")
func_source = source[func_start:]
# Check 1: delete=False used?
print("delete=False:", "delete=False" in func_source) # True
# Check 2: Any cleanup (os.remove, os.unlink, BackgroundTask)?
has_cleanup = "os.remove" in func_source or "os.unlink" in func_source or "background" in func_source.lower()
print("Cleanup exists:", has_cleanup) # False — BUG!
Automated Results on main branch
| # |
Test |
Status |
Detail |
| 1 |
Temp PDF created with delete=False |
FAIL |
delete=False used, file persists after response |
| 2 |
Temp PDF is cleaned up after response |
FAIL |
No os.remove/os.unlink/BackgroundTask cleanup found |
| 3 |
FileResponse uses BackgroundTask for cleanup |
FAIL |
No BackgroundTask attached |
Summary: PASSED=0 FAILED=3
Fix
- Adding
from starlette.background import BackgroundTask import
- Attaching
background=BackgroundTask(os.unlink, tmp_path) to the FileResponse
Location
apps/backend/app/routers/reports.py:129-132Description
The
download_pdfendpoint creates a temporary PDF file withtempfile.NamedTemporaryFile(delete=False)and returns it viaFileResponse. However, the file is never deleted after the response is sent. On a long-running server, each PDF generation leaks a temp file, accumulating disk usage over time.Reproduction (on
mainbranch)Buggy Code
Reproduction Script (
reproduce_bug.py)Automated Results on
mainbranchdelete=Falsedelete=Falseused, file persists after responseos.remove/os.unlink/BackgroundTask cleanup foundFileResponseusesBackgroundTaskfor cleanupBackgroundTaskattachedSummary: PASSED=0 FAILED=3
Fix
from starlette.background import BackgroundTaskimportbackground=BackgroundTask(os.unlink, tmp_path)to theFileResponse