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 = NoneView on GitHub (pinned to 51f49dea19)
Solutions
- Restore the missing profile from backup, or re-assign the generation to an existing profile: UPDATE generations SET profile_id='<valid>' WHERE id='<id>';.
- Audit the schema: ensure voice_profiles.id has ON DELETE CASCADE or restrict, and that the ORM relationship matches.
- If the profile is genuinely gone, delete the orphaned generation too, then re-export will not be needed.
- 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
- Add an ON DELETE CASCADE (or RESTRICT) FK from generations.profile_id to voice_profiles.id.
- Run a periodic orphan check: SELECT id FROM generations WHERE profile_id NOT IN (SELECT id FROM voice_profiles).
- Never delete profiles via raw SQL without handling their generations.
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
- Audio file not found: {sample.audio_path}
- Audio file not found: {audio_path}
- Generation {generation_id} not found
- HTTP ${res.status}
- No profile selected
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/ec56c0d31014819c.
Report an issue: GitHub.