jamiepine/voicebox · error · ValueError

Profile {generation.profile_id} not found

Error message

Profile {generation.profile_id} not found

What it means

Raised by export_generation_to_zip after the generation row is found but its profile_id does not resolve to a VoiceProfile (export_import.py:266-267). The generation references a profile that no longer exists — a dangling foreign key. This indicates the profile was deleted without cascading to (or before) its generations.

Source

Thrown at backend/services/export_import.py:267

    Args:
        generation_id: Generation ID to export
        db: Database session
        
    Returns:
        ZIP file contents as bytes
        
    Raises:
        ValueError: If generation not found
    """
    # Get generation
    generation = db.query(DBGeneration).filter_by(id=generation_id).first()
    if not generation:
        raise ValueError(f"Generation {generation_id} not found")
    
    # Get profile info
    profile = db.query(DBVoiceProfile).filter_by(id=generation.profile_id).first()
    if not profile:
        raise ValueError(f"Profile {generation.profile_id} not found")
    
    # Get all versions for this generation
    versions = (
        db.query(DBGenerationVersion)
        .filter_by(generation_id=generation_id)
        .order_by(DBGenerationVersion.created_at)
        .all()
    )

    # Create ZIP in memory
    zip_buffer = io.BytesIO()
    
    with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
        # Build version manifest entries
        version_entries = []
        for v in versions:
            v_path = config.resolve_storage_path(v.audio_path)
            effects_chain = None

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Restore the missing profile from backup, or re-assign the generation to an existing profile: UPDATE generations SET profile_id='<valid>' WHERE id='<id>';.
  2. Audit the schema: ensure voice_profiles.id has ON DELETE CASCADE or restrict, and that the ORM relationship matches.
  3. If the profile is genuinely gone, delete the orphaned generation too, then re-export will not be needed.
  4. Add a DB-level foreign key constraint if one is missing so this cannot recur.

Example fix

-- before: orphaned generation
SELECT id FROM generations WHERE profile_id NOT IN (SELECT id FROM voice_profiles);
-- after: reassign to an existing profile, then add the constraint
UPDATE generations SET profile_id='<existing>' WHERE id='<orphan>';
Defensive patterns

Strategy: validation

Validate before calling

def export_generation_safe(generation_id: str, db: Session) -> bytes:
    gen = db.query(DBGeneration).filter_by(id=generation_id).first()
    if not gen:
        raise HTTPException(404, 'Generation not found')
    if not db.query(DBVoiceProfile).filter_by(id=gen.profile_id).first():
        raise HTTPException(409, 'Generation references a deleted profile; repair the DB before exporting.')
    return export_generation_to_zip(generation_id, db)

Type guard

null

Try / catch

try:
    zip_bytes = export_generation_to_zip(generation_id, db)
except ValueError as e:
    msg = str(e)
    if 'not found' in msg and 'Profile' in msg:
        raise HTTPException(409, msg)
    raise HTTPException(400, msg)

Prevention

When it happens

Trigger: Profile was hard-deleted while its generation rows remained; manual SQL deleted from voice_profiles without updating generations; a foreign-key constraint was disabled or absent at the schema level; the generation was imported and assigned to a profile_id that was later removed.

Common situations: Manual DB cleanup script that deleted profiles but not their generations; cascading FK not configured in the ORM model; orphaned rows after a partial migration.

Related errors


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