jamiepine/voicebox · error · ValueError

Sample file not found in ZIP: {zip_path}

Error message

Sample file not found in ZIP: {zip_path}

What it means

For each filename key in samples.json the importer expects a matching samples/{filename} entry in the ZIP namelist. If it's absent the importer raises rather than silently skipping referenced audio. The path is built with a forward slash: f"samples/{filename}".

Source

Thrown at backend/services/export_import.py:213

                    try:
                        from .profiles import upload_avatar
                        await upload_avatar(profile.id, tmp_path, db)
                    finally:
                        Path(tmp_path).unlink(missing_ok=True)
                except Exception as e:
                    # Avatar import is optional - continue even if it fails
                    pass

            for filename, reference_text in samples_data.items():
                # Validate filename
                if not filename.endswith('.wav'):
                    raise ValueError(f"Invalid sample filename: {filename} (must be .wav)")
                
                # Extract audio file to temp location
                zip_path = f"samples/{filename}"
                
                if zip_path not in namelist:
                    raise ValueError(f"Sample file not found in ZIP: {zip_path}")
                
                # Extract to temporary file
                import tempfile
                with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
                    tmp.write(zip_file.read(zip_path))
                    tmp_path = tmp.name
                
                try:
                    # Add sample to profile
                    await add_profile_sample(
                        profile.id,
                        tmp_path,
                        reference_text,
                        db,
                    )
                finally:
                    # Clean up temp file
                    Path(tmp_path).unlink(missing_ok=True)

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Re-export so samples.json and the audio entries stay consistent.
  2. Check case and path separators — namelist uses forward slashes; rebuild on the same OS if needed.
  3. Remove orphan keys from samples.json or add the missing audio entries.

Example fix

# before — samples.json says 'abc.wav' but the zip has 'samples/ABC.wav'
# after — keep names consistent: lowercase keys, matching 'samples/<name>' entries, forward slashes
Defensive patterns

Strategy: validation

Validate before calling

import io, json, zipfile

def samples_match_entries(file_bytes) -> bool:
    with zipfile.ZipFile(io.BytesIO(file_bytes)) as z:
        names = set(z.namelist())
        return all(f"samples/{k}" in names for k in json.loads(z.read("samples.json")))

Try / catch

try:
    await import_profile_from_zip(file_bytes, db)
except ValueError as e:
    if "Sample file not found in ZIP" in str(e):
        # reconcile samples.json keys with archive entries (case/separators)
        ...
    raise

Prevention

When it happens

Trigger: samples.json references 'abc.wav' but the archive contains 'samples/ABC.wav' (case mismatch), the audio entry was never added, or backslash separators from a Windows-built zip don't match the forward-slash lookup.

Common situations: Hand-edited samples.json not matching zip contents; case-sensitivity crossing OSes (Linux import of a Windows-built zip); partial zip assembly.

Related errors


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