jamiepine/voicebox · error · FileNotFoundError
Audio for capture {capture_id} is missing
Error message
Audio for capture {capture_id} is missing What it means
Raised as FileNotFoundError (translated to HTTP 410 Gone by the /captures/{id}/retranscribe route) when the capture row exists but the audio file at row.audio_path cannot be resolved to an existing path via config.resolve_storage_path. This signals the metadata is present but the underlying asset is gone — hence 410 rather than 404. It fires before any Whisper call.
Source
Thrown at backend/services/captures.py:220
row.refinement_flags = json.dumps(flags.to_dict())
db.commit()
db.refresh(row)
return _to_response(row)
async def retranscribe_capture(
capture_id: str,
stt_model: Optional[str],
language: Optional[str],
db: Session,
) -> Optional[CaptureResponse]:
row = db.query(DBCapture).filter(DBCapture.id == capture_id).first()
if not row:
return None
resolved = config.resolve_storage_path(row.audio_path)
if not resolved or not resolved.exists():
raise FileNotFoundError(f"Audio for capture {capture_id} is missing")
whisper = get_whisper_model()
resolved_stt = stt_model or whisper.model_size
transcript = await whisper.transcribe(str(resolved), language, resolved_stt)
row.transcript_raw = transcript
row.stt_model = resolved_stt
if language:
row.language = language
# Refined text is stale after a fresh STT pass — force a re-refine.
row.transcript_refined = None
row.llm_model = None
row.refinement_flags = None
db.commit()
db.refresh(row)
return _to_response(row)
View on GitHub (pinned to 51f49dea19)
Solutions
- Confirm the configured storage roots include the capture audio location and the file is present on disk.
- If the asset is permanently lost, delete the capture row (DELETE /captures/{id}) rather than retrying retranscribe.
- Treat HTTP 410 from this endpoint as 'asset gone' — re-recording is the recovery, not a retry.
- Audit audio_path values for absolute paths that break after a data-dir move.
Example fix
# before
resolved = config.resolve_storage_path(row.audio_path)
if not resolved or not resolved.exists():
raise FileNotFoundError(f"Audio for capture {capture_id} is missing")
# after (record the loss on the row so list views can surface it)
resolved = config.resolve_storage_path(row.audio_path)
if not resolved or not resolved.exists():
row.audio_missing = True
db.commit()
raise FileNotFoundError(f"Audio for capture {capture_id} is missing") Defensive patterns
Strategy: try-catch
Validate before calling
async function retranscribeOnlyIfAudioExists(api, captureId) {
const r = await api.getCaptureAudio(captureId, { method: 'HEAD' });
if (!r.ok) throw new Error('capture audio is missing');
return api.retranscribeCapture(captureId, payload);
} Type guard
function captureHasAudioRow(capture) {
return Boolean(capture && typeof capture.audio_path === 'string' && capture.audio_path.length);
} Try / catch
try { await api.retranscribeCapture(captureId, payload); }
catch (e) {
if (e.status === 410) { markCaptureAudioMissing(captureId); notify('Original audio is gone — please re-record'); }
else if (e.status === 404) { dropCapture(captureId); }
else throw e;
} Prevention
- Treat 410 from retranscribe as permanent asset loss — don't retry, re-record.
- Keep capture audio files within the configured storage roots.
- Audit audio_path values after any data-dir migration.
When it happens
Trigger: POST /captures/{capture_id}/retranscribe for a capture whose audio file was deleted from disk (manual cleanup, partial backup restore, moved DATA_DIR), or whose audio_path points outside the configured storage roots so resolve_storage_path returns None.
Common situations: Data directory migrated/restored incompletely; a cleanup script removed capture audio but left DB rows; audio_path stored as an absolute path that no longer exists after a host/path rename; storage root not configured so resolution fails.
Related errors
- Audio file not found
- Source audio file not found
- Audio file not found
- Story item or version not found
- Failed to clear cache: {str(e)}
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/c681712ace9d1e90.
Report an issue: GitHub.