jamiepine/voicebox · error · ValueError

Audio file not found: {audio_path}

Error message

Audio file not found: {audio_path}

What it means

resolve_storage_path() returned a real Path but that file does not exist() on disk. Distinct from error 231 (un-resolvable path): here the path resolves but the bytes are gone. The message uses the resolved Path so the operator knows where the file was expected.

Source

Thrown at backend/services/export_import.py:108

            },
            "has_avatar": has_avatar,
        }
        zip_file.writestr("manifest.json", json.dumps(manifest, indent=2))

        # Create samples.json mapping
        samples_data = {}
        profile_dir = config.get_profiles_dir() / profile_id

        for sample in samples:
            # Get filename from audio_path (should be {sample_id}.wav)
            audio_path = config.resolve_storage_path(sample.audio_path)
            if audio_path is None:
                raise ValueError(f"Audio file not found: {sample.audio_path}")
            filename = audio_path.name

            # Read audio file
            if not audio_path.exists():
                raise ValueError(f"Audio file not found: {audio_path}")

            # Add to samples directory in ZIP
            zip_path = f"samples/{filename}"
            zip_file.write(audio_path, zip_path)

            # Map filename to reference text
            samples_data[filename] = sample.reference_text

        zip_file.writestr("samples.json", json.dumps(samples_data, indent=2))
    
    zip_buffer.seek(0)
    return zip_buffer.read()


async def import_profile_from_zip(file_bytes: bytes, db: Session) -> VoiceProfileResponse:
    """
    Import a voice profile from a ZIP archive.
    

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Restore the missing .wav from backup to the resolved path.
  2. If unrecoverable, delete the orphaned DBProfileSample row and re-record.
  3. Check filesystem permissions on the profiles directory.

Example fix

# before
if not audio_path.exists():
    raise ValueError(f"Audio file not found: {audio_path}")

# after — skip missing with a warning rather than failing the whole export
if not audio_path.exists():
    logger.warning("missing sample %s for profile %s; skipping", audio_path, profile_id)
    continue
Defensive patterns

Strategy: validation

Validate before calling

from backend import config
from backend.database import ProfileSample as DBProfileSample

def all_sample_files_present(profile_id, db) -> bool:
    for s in db.query(DBProfileSample).filter_by(profile_id=profile_id):
        p = config.resolve_storage_path(s.audio_path)
        if p is None or not p.exists():
            return False
    return True

Try / catch

try:
    data = export_profile_to_zip(pid, db)
except ValueError as e:
    if "Audio file not found" in str(e):
        # prompt user to repair/re-record the missing sample
        ...
    raise

Prevention

When it happens

Trigger: Sample file deleted/moved from disk while the DB row remains; backup restored the DB but not the audio; filesystem permissions making exists() return False.

Common situations: Manual cleanup of the profiles directory; antivirus quarantining .wav files; partial disk failure; sync tool that didn't pull audio files.

Related errors


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