jamiepine/voicebox · error · HTTPException
Sample not found
Error message
Sample not found
What it means
Returned as a 404 from GET /audio/samples/{sample_id} when no ProfileSample row matches the given id in the database. The lookup is a direct db.query(...).filter_by(id=sample_id).first(); any id not present (typo, wrong scope, deleted sample) yields None and triggers this. Pure not-found, no file or config involvement.
Source
Thrown at backend/routes/audio.py:77
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)
if audio_path is None or not audio_path.is_file():
raise HTTPException(status_code=404, detail="Audio file not found")
return FileResponse(
audio_path,
media_type="audio/wav",
filename=f"sample_{sample_id}.wav",
)
View on GitHub (pinned to 51f49dea19)
Solutions
- Confirm sample_id is the current id from the samples list endpoint, not a cached value.
- Verify the ProfileSample row exists: SELECT * FROM profile_samples WHERE id = ?.
- If the sample was deleted intentionally, refresh the client's sample list.
- Add client-side handling for 404 on sample fetch to silently drop the reference.
Defensive patterns
Strategy: validation
Validate before calling
// Fetch the samples list first; only request audio for ids that appear in it.
const samples = await listSamples();
const valid = samples.some(s => s.id === sampleId);
if (!valid) throw new Error('Sample id not in current list'); Type guard
function isKnownSample(sampleId: string, known: { id: string }[]): boolean {
return known.some(s => s.id === sampleId);
} Try / catch
try {
const r = await fetch(`/audio/samples/${sampleId}`);
if (r.status === 404) { dropStaleSample(sampleId); return; }
play(await r.blob());
} catch (e) { showNetworkError(e); } Prevention
- Always source sample ids from the live samples list, never from cached state.
- After deleting a sample, remove its id from the client immediately.
- Treat 404 on sample fetch as 'remove reference' rather than an error.
When it happens
Trigger: GET /audio/samples/{sample_id} with an id that does not exist in the profile_samples table — e.g. an old/cached id from the client, a sample that was deleted, or an id from a different user/profile scope.
Common situations: Frontend holds a stale sample id after the user deleted/re-profiled; the id is copy-pasted wrong; test fixtures reference a sample that wasn't seeded.
Related errors
- Generation failed; no audio available
- Audio file not found
- Generation has no audio file
- Audio file not found
- Sample not found
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/b9918a04be127a14.
Report an issue: GitHub.