jamiepine/voicebox · error · HTTPException
Generation failed; no audio available
Error message
Generation failed; no audio available
What it means
Returned as a 404 from GET /audio/{generation_id} when a generation record exists, its status is 'failed', and there is no playable audio artifact on disk (resolve_storage_path returned None or the path is not a regular file). The handler deliberately distinguishes a failed generation from a missing file so the frontend can show 'generation failed' rather than a generic 404. It is a data-state error, not a code bug.
Source
Thrown at backend/routes/audio.py:61
filename=f"generation_{version.generation_id}_{version.label}{audio_path.suffix}",
)
@router.get("/audio/{generation_id}")
async def get_audio(generation_id: str, db: Session = Depends(get_db)):
"""Serve generated audio file (serves the default version)."""
generation = await history.get_generation(generation_id, db)
if not generation:
raise HTTPException(status_code=404, detail="Generation not found")
audio_path = config.resolve_storage_path(generation.audio_path)
if audio_path is None or not audio_path.is_file():
detail = (
"Generation failed; no audio available"
if generation.status == "failed"
else "Audio file not found"
)
raise HTTPException(status_code=404, detail=detail)
return FileResponse(
audio_path,
media_type=_audio_media_type(audio_path),
filename=f"generation_{generation_id}{audio_path.suffix}",
)
@router.get("/samples/{sample_id}")
async def get_sample_audio(sample_id: str, db: Session = Depends(get_db)):
"""Serve profile sample audio file."""
from ..database import ProfileSample as DBProfileSample
sample = db.query(DBProfileSample).filter_by(id=sample_id).first()
if not sample:
raise HTTPException(status_code=404, detail="Sample not found")
audio_path = config.resolve_storage_path(sample.audio_path)View on GitHub (pinned to 51f49dea19)
Solutions
- Inspect the generation row's status and error fields: if status is 'failed', surface the upstream failure reason to the user instead of retrying the audio fetch.
- Verify config.resolve_storage_path(generation.audio_path) returns a real path and that STORAGE_DIR matches where jobs actually write output.
- If failed rows are stale, delete or re-run the generation so it produces a fresh audio_path.
- Guard the frontend: when generation status is 'failed', show the failure UI and do not request the audio stream.
Example fix
// before
const audio = await fetch(`/audio/${id}`); // 404 on failed gens
// after
const gen = await getGeneration(id);
if (gen.status === 'failed') {
showError(gen.error || 'Generation failed');
} else {
const audio = await fetch(`/audio/${id}`);
} Defensive patterns
Strategy: validation
Validate before calling
// Before requesting audio, check the generation status from the generation detail endpoint.
const gen = await getGeneration(generationId);
if (gen.status === 'failed') {
// do not fetch /audio/{id}; show the failure instead
throw new Error('Generation failed; audio will not be available');
} Type guard
type GenerationState = 'pending' | 'completed' | 'failed';
function isAudioAvailable(gen: { status: GenerationState; audio_path: string | null }): boolean {
return gen.status === 'completed' && !!gen.audio_path;
} Try / catch
try {
const r = await fetch(`/audio/${id}`);
if (r.status === 404) {
const body = await r.json();
if (body.detail === 'Generation failed; no audio available') {
showFailureUI();
} else {
showMissingFileUI();
}
return;
}
play(await r.blob());
} catch (e) {
showNetworkError(e);
} Prevention
- Gate the audio request on generation.status === 'completed' and a non-null audio_path.
- Show the upstream failure reason in the UI when status is 'failed' instead of requesting audio.
- Do not cache audio URLs for failed or pending generations.
When it happens
Trigger: GET /audio/{generation_id} where the generation row has status=='failed' and generation.audio_path is null, empty, outside the configured storage root, or points to a non-existent/non-regular file. Happens after a TTS/voice-clone job that errored before writing audio.
Common situations: The TTS engine or model download crashed mid-generation; the worker marked status failed but never wrote the file. Or storage was migrated/cleaned and stale failed rows remain. Or config.resolve_storage_path rejects the stored relative path after a STORAGE_DIR change.
Related errors
- Audio file not found
- Audio file not found
- Sample not found
- Source audio file not found
- Generation has no audio file
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/7145047b81684cf3.
Report an issue: GitHub.