{"record":{"id":"b686cdf9848528bf","repo":"jamiepine/voicebox","slug":"profile-profile-id-not-found-b686cd","errorCode":null,"errorMessage":"Profile {profile_id} not found","messagePattern":"Profile (.+?) not found","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/services/profiles.py","lineNumber":222,"sourceCode":"    db: Session,\n) -> ProfileSampleResponse:\n    \"\"\"\n    Add a sample to a voice profile.\n\n    Args:\n        profile_id: Profile ID\n        audio_path: Path to temporary audio file\n        reference_text: Transcript of audio\n        db: Database session\n\n    Returns:\n        Created sample\n    \"\"\"\n    import asyncio\n\n    profile = db.query(DBVoiceProfile).filter_by(id=profile_id).first()\n    if not profile:\n        raise ValueError(f\"Profile {profile_id} not found\")\n\n    # Validate and load audio in a single pass, off the event loop\n    is_valid, error_msg, audio, sr = await asyncio.to_thread(\n        validate_and_load_reference_audio, audio_path\n    )\n    if not is_valid:\n        raise ValueError(f\"Invalid reference audio: {error_msg}\")\n\n    sample_id = str(uuid.uuid4())\n    profile_dir = config.get_profiles_dir() / profile_id\n    profile_dir.mkdir(parents=True, exist_ok=True)\n\n    dest_path = profile_dir / f\"{sample_id}.wav\"\n    await asyncio.to_thread(save_audio, audio, str(dest_path), sr)\n\n    db_sample = DBProfileSample(\n        id=sample_id,\n        profile_id=profile_id,","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/services/profiles.py#L204-L240","documentation":"Raised by add_profile_sample() when no DBVoiceProfile row matches the given profile_id. The lookup is an exact id match (filter_by(id=profile_id).first()); unlike name lookup it is not case-insensitive and does not fall back to name. Raised before any audio processing.","triggerScenarios":"Calling add_profile_sample with a profile_id that was never created, was deleted, or is misspelled/truncated. Passing a profile name here instead of the UUID id will also fail.","commonSituations":"Client stored the profile name but passed it where the id is expected; using an id from a stale/local DB after the server DB was reset; race where the sample upload starts before the create transaction committed.","solutions":["Verify the profile exists (GET /profiles/{id}) before uploading a sample.","Make sure you pass the profile's UUID id, not its display name — use get_profile_orm_by_name_or_id to resolve names.","Re-seed or recreate the profile if the DB was reset."],"exampleFix":"// before\nadd_profile_sample(profile_id=\"Morgan\", ...)\n// after - resolve name to id first\nprofile = get_profile_orm_by_name_or_id(\"Morgan\", db)\nif profile is None: raise\nadd_profile_sample(profile_id=profile.id, ...)","handlingStrategy":"validation","validationCode":"def profile_exists(profile_id: str, db) -> bool:\n    from ..database import VoiceProfile\n    return db.query(VoiceProfile).filter_by(id=profile_id).first() is not None\n\n# resolve names to ids before calling add_profile_sample\nprofile = get_profile_orm_by_name_or_id(name_or_id, db)\nif profile is None:\n    raise HTTPException(404, \"profile not found\")\nsample = await add_profile_sample(profile.id, audio_path, ref_text, db)","typeGuard":"def is_uuid_like(s: str) -> bool:\n    import uuid\n    try:\n        uuid.UUID(s); return True\n    except (ValueError, AttributeError, TypeError):\n        return False","tryCatchPattern":"try:\n    await add_profile_sample(profile_id, audio_path, ref_text, db)\nexcept ValueError as e:\n    if \"not found\" in str(e):\n        raise HTTPException(404, str(e))\n    raise","preventionTips":["Always pass the profile id (UUID), not the name, to add_profile_sample.","Resolve names via get_profile_orm_by_name_or_id at the API boundary.","GET the profile before upload to fail fast with a clear 404."],"tags":["profiles","samples","not-found","create"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}