jamiepine/voicebox · error · ValueError
No audio file found in ZIP archive
Error message
No audio file found in ZIP archive
What it means
Raised during generation import when no entry in the ZIP namelist both starts with 'audio/' and ends with '.wav' (export_import.py:382-384). The manifest passed validation but the audio payload the manifest describes is absent or named differently. The importer takes audio_files[0], so an empty list is fatal.
Source
Thrown at backend/services/export_import.py:384
if "version" not in manifest_data:
raise ValueError("Invalid manifest.json: missing version")
if "generation" not in manifest_data:
raise ValueError("Invalid manifest.json: missing generation data")
generation_data = manifest_data["generation"]
profile_data = manifest_data.get("profile", {})
# Validate required fields
required_fields = ["text", "language", "duration"]
for field in required_fields:
if field not in generation_data:
raise ValueError(f"Invalid manifest.json: missing generation.{field}")
# Find audio file in archive
audio_files = [f for f in namelist if f.startswith("audio/") and f.endswith(".wav")]
if not audio_files:
raise ValueError("No audio file found in ZIP archive")
audio_file_path = audio_files[0]
# Check if we should match an existing profile or create metadata
profile_id = None
profile_name = profile_data.get("name", "Unknown Profile")
# Try to find matching profile by name
if profile_name and profile_name != "Unknown Profile":
existing_profile = db.query(DBVoiceProfile).filter_by(name=profile_name).first()
if existing_profile:
profile_id = existing_profile.id
# If no matching profile, use a placeholder or the first available profile
if not profile_id:
# Get any profile, or None if no profiles exist
any_profile = db.query(DBVoiceProfile).first()
if any_profile:View on GitHub (pinned to 51f49dea19)
Solutions
- Unzip the archive and confirm a file exists at exactly audio/<something>.wav (case-sensitive on Linux).
- If the audio is elsewhere, move it under audio/ and re-zip preserving paths.
- Re-export from the source instance.
- If the source audio is .mp3, convert to .wav before importing — this importer accepts WAV only.
Example fix
# before: audio at archive root zip -r gen.zip manifest.json clip.wav # after: audio under audio/ mkdir audio && mv clip.wav audio/clip.wav zip -r gen.zip manifest.json audio/clip.wav
Defensive patterns
Strategy: validation
Validate before calling
import zipfile, io
def archive_has_wav_audio(file_bytes: bytes) -> bool:
with zipfile.ZipFile(io.BytesIO(file_bytes)) as z:
return any(n.startswith('audio/') and n.endswith('.wav') for n in z.namelist()) Type guard
null
Try / catch
try:
result = await import_generation_from_bytes(file_bytes, db)
except ValueError as e:
if str(e) == 'No audio file found in ZIP archive':
raise HTTPException(400, 'Archive has no audio/*.wav entry; re-export with the audio included.')
raise HTTPException(400, str(e)) Prevention
- Always re-zip with the audio/ prefix intact.
- When rebuilding archives, use `zip -r` from a directory whose structure matches export_generation_to_zip.
- Accept only WAV for this importer — convert formats upstream.
When it happens
Trigger: Archive was rebuilt after editing and the audio entry was placed at the root instead of under audio/; the audio was renamed to .mp3 or omitted; a partial export wrote the manifest before the audio and then crashed.
Common situations: Re-zipping by hand and losing the audio/ prefix; exporter bug that wrote a different path; format conversion stripped the .wav extension.
Related errors
- Unsupported audio format '{suffix}'. Allowed: {sorted(IMPORT
- Empty audio file.
- {e}
- ZIP archive missing manifest.json
- ZIP archive missing samples.json
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/aca33f146c69ab2a.
Report an issue: GitHub.