{"record":{"id":"dd8b3b0625ad31ab","repo":"jamiepine/voicebox","slug":"source-audio-file-not-found","errorCode":null,"errorMessage":"Source audio file not found","messagePattern":"Source audio file not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"backend/routes/effects.py","lineNumber":45,"sourceCode":"        raise HTTPException(status_code=404, detail=\"Generation not found\")\n    if (gen.status or \"completed\") != \"completed\":\n        raise HTTPException(status_code=400, detail=\"Generation is not completed\")\n\n    from ..services import versions as versions_mod\n    from ..utils.effects import apply_effects, validate_effects_chain\n    from ..utils.audio import load_audio\n\n    chain_dicts = [e.model_dump() for e in data.effects_chain]\n    error = validate_effects_chain(chain_dicts)\n    if error:\n        raise HTTPException(status_code=400, detail=error)\n\n    all_versions = versions_mod.list_versions(generation_id, db)\n    clean_version = next((v for v in all_versions if v.effects_chain is None), None)\n    source_path = clean_version.audio_path if clean_version else gen.audio_path\n    resolved_source_path = config.resolve_storage_path(source_path)\n    if resolved_source_path is None or not resolved_source_path.exists():\n        raise HTTPException(status_code=404, detail=\"Source audio file not found\")\n\n    audio, sample_rate = await asyncio.to_thread(load_audio, str(resolved_source_path))\n    processed = await asyncio.to_thread(apply_effects, audio, sample_rate, chain_dicts)\n\n    import soundfile as sf\n\n    buf = io.BytesIO()\n    await asyncio.to_thread(lambda: sf.write(buf, processed, sample_rate, format=\"WAV\"))\n    buf.seek(0)\n\n    return StreamingResponse(\n        buf,\n        media_type=\"audio/wav\",\n        headers={\n            \"Content-Disposition\": f'inline; filename=\"preview_{generation_id}.wav\"',\n            \"Cache-Control\": \"no-cache, no-store\",\n        },\n    )","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/routes/effects.py#L27-L63","documentation":"HTTP 404 raised by POST /effects/preview/{generation_id} when the source audio file cannot be located on disk. The handler resolves the path via config.resolve_storage_path(source_path) (falling back to gen.audio_path when no clean version exists) and raises 404 when resolution returns None or the resolved file does not exist. The generation record exists and is completed, but the underlying audio artifact is missing from storage.","triggerScenarios":"The generation row is present and completed, but the audio file was deleted, moved, or never written (storage misconfiguration, partial migration, manual cleanup of the data dir).","commonSituations":"Storage directory relocated without updating config; data dir pruned by an external script; file write failed silently during generation; path stored as absolute and the host changed.","solutions":["Verify the storage/data directory configured for the backend contains the generated audio files.","If you migrated storage, re-run resolve_storage_path checks or regenerate the audio.","Re-run the generation to reproduce the audio file, then retry the preview.","Confirm config.resolve_storage_path returns a real path for the stored audio_path value."],"exampleFix":"# before\nresolved = config.resolve_storage_path(source_path)\n# after\nresolved = config.resolve_storage_path(source_path)\nif resolved is None or not resolved.exists():\n    logger.error('missing audio for generation %s at %s', generation_id, source_path)\n    # regenerate or restore from backup before previewing","handlingStrategy":"try-catch","validationCode":"import config\nresolved = config.resolve_storage_path(source_path)\nif resolved is None or not resolved.exists():\n    raise RuntimeError('source audio missing on disk')","typeGuard":null,"tryCatchPattern":"const r = await fetch(`/effects/preview/${id}`, { method:'POST', body: JSON.stringify(data) });\nif (r.status === 404 && (await r.json()).detail === 'Source audio file not found') { /* regenerate or restore storage */ }","preventionTips":["Keep the data/storage directory stable and backed up.","Re-run generation if the audio artifact is missing.","Verify config.resolve_storage_path returns existing paths after migrations."],"tags":["effects","http","filesystem","not-found","storage","fastapi"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}