jamiepine/voicebox · warning · HTTPException

File exceeds {IMPORT_AUDIO_MAX_BYTES // (1024 * 1024)} MB li

Error message

File exceeds {IMPORT_AUDIO_MAX_BYTES // (1024 * 1024)} MB limit.

What it means

Returned by POST /generate/import when the cumulative uploaded byte total exceeds IMPORT_AUDIO_MAX_BYTES (200 * 1024 * 1024 = 200 MB). The endpoint streams the upload in 1 MB chunks and checks `total > IMPORT_AUDIO_MAX_BYTES` after each chunk, so the rejection happens mid-stream. HTTP 413 Payload Too Large.

Source

Thrown at backend/routes/generations.py:442

    Designed for the story timeline so users can drop in music or other
    non-TTS audio. The row points at a singleton "Imported Audio" profile
    so the existing generation/story plumbing keeps working unchanged."""
    suffix = Path(file.filename or "").suffix.lower()
    if suffix not in IMPORT_AUDIO_EXTENSIONS:
        raise HTTPException(
            status_code=400,
            detail=f"Unsupported audio format '{suffix}'. Allowed: {sorted(IMPORT_AUDIO_EXTENSIONS)}",
        )

    chunks: list[bytes] = []
    total = 0
    while True:
        chunk = await file.read(1024 * 1024)
        if not chunk:
            break
        total += len(chunk)
        if total > IMPORT_AUDIO_MAX_BYTES:
            raise HTTPException(
                status_code=413,
                detail=f"File exceeds {IMPORT_AUDIO_MAX_BYTES // (1024 * 1024)} MB limit.",
            )
        chunks.append(chunk)
    audio_bytes = b"".join(chunks)
    if not audio_bytes:
        raise HTTPException(status_code=400, detail="Empty audio file.")

    generation_id = str(uuid.uuid4())
    target = config.get_generations_dir() / f"{generation_id}{suffix}"
    target.write_bytes(audio_bytes)

    try:
        audio, sr = load_audio(str(target))
        duration = float(len(audio) / sr) if sr else 0.0
    except Exception as decode_err:
        try:
            target.unlink()

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Compress or trim the audio to under 200 MB before uploading (downsample, convert to mp3/flac).
  2. If larger imports are genuinely needed, raise IMPORT_AUDIO_MAX_BYTES in backend/routes/generations.py AND raise the reverse proxy body limit (e.g. nginx client_max_body_size) to match.
  3. Validate file size client-side before the upload starts to avoid a wasted partial transfer.
  4. For very large media, split into segments.

Example fix

// before
upload(file);

// after
const MAX = 200 * 1024 * 1024;
if (file.size > MAX) { alert(`File exceeds ${MAX/1048576} MB`); return; }
upload(file);
Defensive patterns

Strategy: validation

Validate before calling

const MAX = 200 * 1024 * 1024;
if (file.size > MAX) { alert(`File exceeds ${MAX/1048576} MB`); return; }
await upload(file);

Type guard

function withinImportLimit(file, limitBytes = 200 * 1024 * 1024) {
  return file && typeof file.size === 'number' && file.size <= limitBytes;
}

Try / catch

try {
  const res = await fetch('/generate/import', { method:'POST', body: form });
  if (res.status === 413) { alert('File too large'); return; }
} catch (e) { console.error(e); }

Prevention

When it happens

Trigger: Uploading an audio file larger than 200 MB; uploading a file that is nominally under the limit but the streamed chunks push the running total past it on the last read.

Common situations: Long-form music mixes or uncompressed WAV masters exceeding 200 MB; a reverse proxy (nginx) with its own client_max_body_size set lower intercepting first; browser uploading a folder-compressed blob.

Related errors


AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12). Data as JSON: /api/errors/771bfce535a9dac7. Report an issue: GitHub.