jamiepine/voicebox · warning · HTTPException
File too large. Maximum size is {MAX_FILE_SIZE / (1024 * 102
Error message
File too large. Maximum size is {MAX_FILE_SIZE / (1024 * 1024)}MB What it means
Returned by POST /history/import when `len(content) > MAX_FILE_SIZE` where MAX_FILE_SIZE is hardcoded to 50 * 1024 * 1024 (50 MB). The entire upload is read into memory via `await file.read()` before the check, then rejected with HTTP 400 (note: the status code is 400, though semantically 413 would be more appropriate). This endpoint imports a previously-exported generation ZIP.
Source
Thrown at backend/routes/history.py:52
@router.get("/history/stats")
async def get_stats(db: Session = Depends(get_db)):
"""Get generation statistics."""
return await history.get_generation_stats(db)
@router.post("/history/import")
async def import_generation(
file: UploadFile = File(...),
db: Session = Depends(get_db),
):
"""Import a generation from a ZIP archive."""
MAX_FILE_SIZE = 50 * 1024 * 1024
content = await file.read()
if len(content) > MAX_FILE_SIZE:
raise HTTPException(
status_code=400, detail=f"File too large. Maximum size is {MAX_FILE_SIZE / (1024 * 1024)}MB"
)
try:
result = await export_import.import_generation_from_zip(content, db)
return result
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/history/failed")
async def clear_failed_generations(db: Session = Depends(get_db)):
"""Delete every generation with status='failed'. Used by the UI's 'Clear failed' button (#410)."""
count = await history.delete_failed_generations(db)
return {"deleted": count}
View on GitHub (pinned to 51f49dea19)
Solutions
- Ensure the imported ZIP is under 50 MB — if the contained audio is large, the export ZIP will exceed this.
- If larger imports are needed, raise MAX_FILE_SIZE in backend/routes/history.py and the reverse proxy body limit accordingly.
- Consider changing the status code to 413 for semantic correctness if you touch this code.
- Stream-check the size during read instead of after full buffering to avoid holding oversized payloads in memory.
Example fix
# before
MAX_FILE_SIZE = 50 * 1024 * 1024
if len(content) > MAX_FILE_SIZE:
raise HTTPException(status_code=400, detail=f"File too large...")
# after
MAX_FILE_SIZE = 50 * 1024 * 1024
if len(content) > MAX_FILE_SIZE:
raise HTTPException(status_code=413, detail=f"File too large...") Defensive patterns
Strategy: validation
Validate before calling
const MAX = 50 * 1024 * 1024;
if (file.size > MAX) { alert(`ZIP exceeds ${MAX/1048576} MB`); return; }
await upload(file); Type guard
function withinImportZipLimit(file, limitBytes = 50 * 1024 * 1024) {
return file && typeof file.size === 'number' && file.size <= limitBytes;
} Try / catch
try {
const res = await fetch('/history/import', { method:'POST', body: form });
if (res.status === 400 && /too large/i.test((await res.json()).detail)) {
alert('Import ZIP too large'); return;
}
} catch (e) { console.error(e); } Prevention
- Check file.size before uploading.
- Keep export audio small enough to fit the 50 MB import limit.
- Raise MAX_FILE_SIZE server-side if larger imports are needed (and the proxy limit).
When it happens
Trigger: Uploading a generation ZIP larger than 50 MB; the entire file is already buffered in memory by the time the size is checked, so a 100 MB upload wastes RAM before being rejected.
Common situations: Re-importing a generation whose embedded audio is large; exporting+re-importing after the audio was upscaled; a ZIP bomb or maliciously large archive.
Related errors
- File exceeds {IMPORT_AUDIO_MAX_BYTES // (1024 * 1024)} MB li
- {e}
- Unsupported audio format '{suffix}'. Allowed: {sorted(IMPORT
- Empty audio file.
- Could not decode audio: {decode_err}
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/25c2fa2cb0a87d85.
Report an issue: GitHub.