{"record":{"id":"74b38836e8e950b5","repo":"jamiepine/voicebox","slug":"profile-not-found-profile-id","errorCode":null,"errorMessage":"Profile not found: {profile_id}","messagePattern":"Profile not found: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/services/profiles.py","lineNumber":542,"sourceCode":"\n    For cloned profiles: combines all audio samples into a voice prompt.\n    For preset profiles: returns the engine-specific preset voice reference.\n    For designed profiles: returns the text design prompt (future).\n\n    Args:\n        profile_id: Profile ID\n        db: Database session\n        use_cache: Whether to use cached prompts\n        engine: TTS engine to create prompt for\n\n    Returns:\n        Voice prompt dictionary\n    \"\"\"\n    from ..backends import get_tts_backend_for_engine\n\n    profile = db.query(DBVoiceProfile).filter_by(id=profile_id).first()\n    if not profile:\n        raise ValueError(f\"Profile not found: {profile_id}\")\n\n    voice_type = getattr(profile, \"voice_type\", None) or \"cloned\"\n    validate_profile_engine(profile, engine)\n\n    # ── Preset profiles: return engine-specific voice reference ──\n    if voice_type == \"preset\":\n        if not profile.preset_engine or not profile.preset_voice_id:\n            raise ValueError(f\"Preset profile {profile_id} is missing preset engine metadata\")\n        if profile.preset_engine != engine:\n            raise ValueError(\n                f\"Preset profile {profile_id} only supports engine '{profile.preset_engine}', not '{engine}'\"\n            )\n        return {\n            \"voice_type\": \"preset\",\n            \"preset_engine\": profile.preset_engine,\n            \"preset_voice_id\": profile.preset_voice_id,\n        }\n","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/services/profiles.py#L524-L560","documentation":"Raised by create_voice_prompt_from_profile() when no DBVoiceProfile row matches the supplied profile_id. The function queries DBVoiceProfile by id and immediately aborts if the row is absent, because every subsequent branch (preset/designed/cloned) dereferences profile fields. It is a caller-contract failure: the caller referenced a profile that does not exist in the current database session.","triggerScenarios":"Calling create_voice_prompt_from_profile(profile_id=<id>, db=..., engine=...) where <id> is not present in the voice_profiles table; passing a string vs int id mismatch; passing a profile_id from a different tenant/database; calling after the profile was deleted in another session.","commonSituations":"Stale profile_id cached client-side after deletion; race where a profile is removed between a list call and a generate call; test fixtures that reference hardcoded ids not seeded; typo or copy/paste of an id string; using a database that was not migrated to contain preset/designed seed profiles.","solutions":["Verify the profile exists before calling: profile = db.query(DBVoiceProfile).filter_by(id=profile_id).first(); if not profile: return 404.","Check the profile_id type matches the DBVoiceProfile.id column type (string UUID vs integer) and that you are passing the correct value.","If the id originates from the client, validate it against the database in the API route before reaching the service layer.","Confirm migrations/seeds have run so that referenced profiles (including preset profiles) exist."],"exampleFix":"// before\nprompt = await create_voice_prompt_from_profile(profile_id, db, engine=engine)\n// after\nprofile = db.query(DBVoiceProfile).filter_by(id=profile_id).first()\nif not profile:\n    raise HTTPException(404, f\"Profile not found: {profile_id}\")\nprompt = await create_voice_prompt_from_profile(profile_id, db, engine=engine)","handlingStrategy":"validation","validationCode":"from backend.models import DBVoiceProfile\n\ndef profile_exists(db, profile_id) -> bool:\n    return db.query(DBVoiceProfile).filter_by(id=profile_id).first() is not None\n\n# before calling create_voice_prompt_from_profile\nif not profile_exists(db, profile_id):\n    raise HTTPException(404, f\"Profile not found: {profile_id}\")","typeGuard":null,"tryCatchPattern":"try:\n    prompt = await create_voice_prompt_from_profile(profile_id, db, engine=engine)\nexcept ValueError as e:\n    if \"Profile not found\" in str(e):\n        raise HTTPException(404, str(e))\n    raise","preventionTips":["Always validate profile_id against the DB at the API boundary before reaching service code.","Return 404 immediately for unknown profiles; do not pass stale ids from client caches.","Ensure migrations/seeds have run so referenced profiles exist in every environment."],"tags":["profiles","validation","not-found","database","voicebox"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}