jamiepine/voicebox · error · ValueError

Invalid JSON in archive: {e}

Error message

Invalid JSON in archive: {e}

What it means

Raised inside the profile import's try block when json.loads() on manifest.json or samples.json throws json.JSONDecodeError. The ZIP itself opens fine, but one of the metadata files inside is not valid JSON (export_import.py:237-238). Wrapped as ValueError(f"Invalid JSON in archive: {e}") with the parser's positional detail preserved.

Source

Thrown at backend/services/export_import.py:238

                
                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)
            
            return profile
            
    except zipfile.BadZipFile:
        raise ValueError("Invalid ZIP file")
    except json.JSONDecodeError as e:
        raise ValueError(f"Invalid JSON in archive: {e}")
    except Exception as e:
        if isinstance(e, ValueError):
            raise
        raise ValueError(f"Error importing profile: {str(e)}")


def export_generation_to_zip(generation_id: str, db: Session) -> bytes:
    """
    Export a generation to a ZIP archive.
    
    Args:
        generation_id: Generation ID to export
        db: Database session
        
    Returns:
        ZIP file contents as bytes
        
    Raises:

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Unzip the archive locally and run python -m json.tool manifest.json to find the exact syntax error — the {e} suffix reports line/column.
  2. Re-export the profile from the source instance rather than hand-editing the archive.
  3. If migrating across versions, open the ZIP, fix the JSON in place, and rezip preserving the same internal paths (manifest.json, samples.json, samples/*.wav).
  4. Check for a BOM: strip leading \ufeff from manifest.json before re-zipping.

Example fix

# before: hand-edited manifest with trailing comma
{"version": 1, "profile": {"name": "x",},}
# after: valid JSON
{"version": 1, "profile": {"name": "x"}}
Defensive patterns

Strategy: validation

Validate before calling

import json, zipfile, io

def validate_archive_json(file_bytes: bytes) -> None:
    with zipfile.ZipFile(io.BytesIO(file_bytes)) as z:
        for name in ('manifest.json', 'samples.json'):
            if name not in z.namelist():
                raise ValueError(f'missing {name}')
            try:
                json.loads(z.read(name))
            except json.JSONDecodeError as e:
                raise ValueError(f'{name} is not valid JSON: {e}')

Type guard

null

Try / catch

try:
    profile = await import_profile_from_bytes(file_bytes, db)
except ValueError as e:
    msg = str(e)
    if msg.startswith('Invalid JSON in archive'):
        raise HTTPException(400, 'Archive metadata is malformed JSON. Re-export the profile.')
    raise HTTPException(400, msg)

Prevention

When it happens

Trigger: manifest.json or samples.json contains trailing commas, single quotes, comments, or was hand-edited; the file is UTF-16 with a BOM; the file was overwritten by a stray zip entry that is actually audio/text; partial write during a crash left a truncated JSON document.

Common situations: User edited an exported ZIP by hand to rename a profile; an older or newer export format writes a different schema; a sync tool (Dropbox/OneDrive) uploaded a conflicted copy into the archive; export was interrupted and wrote a partial JSON file.

Understand the failure class

Related errors


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