jamiepine/voicebox · error · ValueError
Invalid manifest.json: missing profile
Error message
Invalid manifest.json: missing profile
What it means
manifest.json must contain a 'profile' object (name/description/language). The importer reads profile_data = manifest_data['profile'] and uses it to build VoiceProfileCreate. Missing 'profile' is rejected before any DB write.
Source
Thrown at backend/services/export_import.py:157
try:
with zipfile.ZipFile(zip_buffer, 'r') as zip_file:
# Validate ZIP structure
namelist = zip_file.namelist()
if "manifest.json" not in namelist:
raise ValueError("ZIP archive missing manifest.json")
if "samples.json" not in namelist:
raise ValueError("ZIP archive missing samples.json")
# Read manifest
manifest_data = json.loads(zip_file.read("manifest.json"))
if "version" not in manifest_data:
raise ValueError("Invalid manifest.json: missing version")
if "profile" not in manifest_data:
raise ValueError("Invalid manifest.json: missing profile")
profile_data = manifest_data["profile"]
# Read samples mapping
samples_data = json.loads(zip_file.read("samples.json"))
if not isinstance(samples_data, dict):
raise ValueError("Invalid samples.json: must be a dictionary")
# Get unique profile name
original_name = profile_data.get("name", "Imported Profile")
unique_name = _get_unique_profile_name(original_name, db)
# Create profile
profile_create = VoiceProfileCreate(
name=unique_name,
description=profile_data.get("description"),
language=profile_data.get("language", "en"),View on GitHub (pinned to 51f49dea19)
Solutions
- Re-export the profile to regenerate a valid manifest.
- If manual, include profile: {name, description, language}.
- Verify you're hitting the profile-import endpoint, not generation-import.
Example fix
// before
{"version": "1.0", "has_avatar": false}
// after
{"version": "1.0", "profile": {"name": "My Voice", "description": "...", "language": "en"}, "has_avatar": false} Defensive patterns
Strategy: validation
Validate before calling
import io, json, zipfile
def manifest_has_profile(file_bytes) -> bool:
with zipfile.ZipFile(io.BytesIO(file_bytes)) as z:
return "profile" in json.loads(z.read("manifest.json")) Type guard
def has_profile_block(m) -> bool:
return isinstance(m, dict) and isinstance(m.get("profile"), dict) Try / catch
try:
await import_profile_from_zip(file_bytes, db)
except ValueError as e:
if "missing profile" in str(e):
# not a profile archive; don't treat as a generic import error
...
raise Prevention
- Validate manifest.profile is a dict before importing.
- Use exporter output as the canonical archive format.
When it happens
Trigger: Manifest edited to remove the profile block; a manifest from an unrelated feature uploaded to the profile-import endpoint; cross-endpoint confusion.
Common situations: Hand-editing the manifest; uploading a generation-export archive (which uses a different top-level shape) to profile import.
Related errors
- Invalid manifest.json: missing version
- ZIP archive missing manifest.json
- ZIP archive missing samples.json
- Invalid samples.json: must be a dictionary
- Invalid manifest.json: missing generation data
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/ed49739b30c0bbab.
Report an issue: GitHub.