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

  1. Confirm sample_id is the current id from the samples list endpoint, not a cached value.
  2. Verify the ProfileSample row exists: SELECT * FROM profile_samples WHERE id = ?.
  3. If the sample was deleted intentionally, refresh the client's sample list.
  4. 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

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


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