jamiepine/voicebox · error · HTTPException

Could not decode audio: {decode_err}

Error message

Could not decode audio: {decode_err}

What it means

Returned by POST /generate/import when `load_audio(str(target))` raises any Exception after the bytes were written to disk. The handler deletes the orphaned target file (best-effort, OSError ignored) and re-raises as HTTP 400 with the original exception text. This means the container/format was accepted by extension but the actual audio decoder (torchaudio/soundfile/etc.) could not parse the contents.

Source

Thrown at backend/routes/generations.py:463

            )
        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()
        except OSError:
            pass
        raise HTTPException(
            status_code=400,
            detail=f"Could not decode audio: {decode_err}",
        ) from decode_err

    profile = _get_or_create_import_profile(db)
    display_name = Path(file.filename or "Imported audio").stem or "Imported audio"

    return await history.create_generation(
        profile_id=profile.id,
        text=display_name,
        language="en",
        audio_path=config.to_storage_path(target),
        duration=duration,
        seed=None,
        db=db,
        generation_id=generation_id,
        status="completed",
        engine="import",

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Read the decode_err message — it usually names the missing codec or parse failure.
  2. Re-encode the source to standard PCM WAV (16-bit, 44.1kHz, mono/stereo) using ffmpeg before importing.
  3. Ensure the server has the required audio decoder backend installed (torchaudio + soundfile/ffmpeg).
  4. If a specific format is unsupported by the decoder, remove it from IMPORT_AUDIO_EXTENSIONS so it fails at the extension check with a clearer message.

Example fix

# before: rename and hope
mv data.bin audio.wav

# after: re-encode to a known-good container
ffmpeg -i data.bin -ar 44100 -ac 1 -sample_fmt s16 audio.wav
Defensive patterns

Strategy: try-catch

Validate before calling

// Best-effort: validate extension + non-empty before the decode attempt
if (!hasImportableAudioExt(file.name) || file.size === 0) return;
// Full decode validation only happens server-side; cannot pre-verify codec here.
await upload(file);

Type guard

// Cannot type-guard codec validity client-side; guard extension + size only
function plausiblyDecodable(file) {
  return isNonEmptyFile(file) && hasImportableAudioExt(file.name);
}

Try / catch

try {
  const res = await fetch('/generate/import', { method:'POST', body: form });
  if (res.status === 400 && /decode/i.test((await res.json()).detail)) {
    alert('Could not decode — re-encode to standard WAV/MP3');
    return;
  }
} catch (e) { console.error(e); }

Prevention

When it happens

Trigger: A file with a whitelisted extension (e.g. .wav) whose contents are corrupt, truncated, or not actually that format; an encoding variant the backend decoder doesn't support (e.g. 32-bit float WAV when only 16-bit PCM is supported); a password-protected or DRM blob renamed to .mp3.

Common situations: Renamed a non-audio file to .wav; partial download of an audio file; exotic codec profile (e.g. very high sample rate, unusual channel layout) unsupported by the bundled decoder library; FFmpeg/torchaudio backend missing on the server.

Related errors


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