jamiepine/voicebox · error · ValueError

Audio file not found: {sample.audio_path}

Error message

Audio file not found: {sample.audio_path}

What it means

For each sample, export calls config.resolve_storage_path(sample.audio_path); if it returns None (the stored relative path can't be mapped under the configured storage root), export raises ValueError using the stored audio_path string. This catches corrupt rows whose audio_path is inconsistent with the current storage layout.

Source

Thrown at backend/services/export_import.py:103

            "version": "1.0",
            "profile": {
                "name": profile.name,
                "description": profile.description,
                "language": profile.language,
            },
            "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()

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Confirm the configured storage root (config.get_data_dir / get_profiles_dir) matches where sample files actually live.
  2. Inspect sample.audio_path — it should be a relative path under the storage root.
  3. Relink the audio files or fix the stored paths in the DB.

Example fix

# before
audio_path = config.resolve_storage_path(sample.audio_path)
if audio_path is None:
    raise ValueError(f"Audio file not found: {sample.audio_path}")

# after — log resolved root + offending path for diagnosis
audio_path = config.resolve_storage_path(sample.audio_path)
if audio_path is None:
    logger.error("unresolvable %r under %s", sample.audio_path, config.get_profiles_dir())
    raise ValueError(f"Audio file not found: {sample.audio_path}")
Defensive patterns

Strategy: validation

Validate before calling

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

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

Try / catch

try:
    data = export_profile_to_zip(pid, db)
except ValueError as e:
    if str(e).startswith("Audio file not found"):
        # data-integrity issue; surface for repair
        ...
    raise

Prevention

When it happens

Trigger: Storage root config changed since the sample was created (different DATA_DIR/profiles dir); audio_path stored as an absolute or stray path that resolve_storage_path rejects; sample row pointing outside the allowed storage root.

Common situations: Data directory moved; DB migrated without migrating storage paths; manual DB edit inserting a bad path.

Related errors


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