jamiepine/voicebox · error · HTTPException

str(e)

Error message

str(e)

What it means

Raised (HTTP 500) by POST /transcribe as the catch-all for any non-HTTPException during transcription (genuine HTTPExceptions, including the 202 'model downloading', are re-raised first). The detail is raw str(e). The body of the handler loads/decodes audio, optionally re-encodes to WAV, and calls whisper_model.transcribe — so the underlying cause is typically a decode failure, a Whisper runtime error, or a model-loading problem that wasn't caught by the is_loaded/_is_model_cached guards.

Source

Thrown at backend/routes/transcription.py:101

                status_code=202,
                detail={
                    "message": f"Whisper model {model_size} is being downloaded. Please wait and try again.",
                    "model_name": progress_model_name,
                    "downloading": True,
                },
            )

        text = await whisper_model.transcribe(stt_path, language, model_size)

        return models.TranscriptionResponse(
            text=text,
            duration=duration,
        )

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    finally:
        Path(tmp_path).unlink(missing_ok=True)
        if stt_path != tmp_path:
            Path(stt_path).unlink(missing_ok=True)

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Read the server traceback — str(e) is only the surface; the logged exception has the frame.
  2. Validate the upload is non-empty before processing (the route reads in 1MB chunks but doesn't reject empty input).
  3. Ensure the Whisper model for the chosen size is fully downloaded (let the 202 download flow finish before retrying).
  4. Replace detail=str(e) with a generic message and log server-side to avoid leaking internals.
  5. Confirm ffmpeg is installed if inputs include webm/opus/m4a.

Example fix

# before
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# after
    except Exception:
        logger.exception("transcribe failed for %s", tmp_path)
        raise HTTPException(status_code=500, detail="Transcription failed; see server logs")
Defensive patterns

Strategy: try-catch

Validate before calling

function looksLikeUsableAudio(file) {
  return file && file.size > 1024 && /\.(wav|mp3|m4a|ogg|flac|aac|webm|opus)$/i.test(file.name || '');
}
if (!looksLikeUsableAudio(file)) { notify('Audio file is empty or unsupported'); return; }

Type guard

function isNonEmptyAudioFile(file) {
  return file instanceof File && file.size > 0 && Boolean(file.name);
}

Try / catch

try { await api.transcribe(file, language, model); }
catch (e) {
  if (e.status === 500) { notify('Transcription failed; check server logs and audio file'); }
  else if (e.status === 202) { notify('Model downloading; retry shortly'); }
  else throw e;
}

Prevention

When it happens

Trigger: Uploaded file is zero-length or an unreadable container after the upload read; librosa load succeeds but the re-encoded .stt.wav is malformed; whisper_model.transcribe throws (OOM, unsupported sample rate, incomplete model download despite the cache check).

Common situations: Browser recording truncated/empty; a partially downloaded Whisper model passes _is_model_cached but fails at inference; GPU/MPS OOM on a long file; ffmpeg/audioread backend missing on the host so decode of exotic containers fails inside transcribe.

Related errors


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