{"record":{"id":"11db0f91eb3821dd","repo":"jamiepine/voicebox","slug":"sample-audio-not-found-for-profile-profile-id","errorCode":null,"errorMessage":"Sample audio not found for profile {profile_id}","messagePattern":"Sample audio not found for profile (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/services/profiles.py","lineNumber":585,"sourceCode":"            \"design_prompt\": profile.design_prompt,\n        }\n\n    if engine not in CLONING_ENGINES:\n        raise ValueError(f\"Engine '{engine}' does not support cloned voice profiles\")\n\n    # ── Cloned profiles: create from audio samples ──\n    samples = db.query(DBProfileSample).filter_by(profile_id=profile_id).all()\n\n    if not samples:\n        raise ValueError(f\"No samples found for profile {profile_id}\")\n\n    tts_model = get_tts_backend_for_engine(engine)\n\n    if len(samples) == 1:\n        sample = samples[0]\n        sample_audio_path = config.resolve_storage_path(sample.audio_path)\n        if sample_audio_path is None:\n            raise ValueError(f\"Sample audio not found for profile {profile_id}\")\n        voice_prompt, _ = await tts_model.create_voice_prompt(\n            str(sample_audio_path),\n            sample.reference_text,\n            use_cache=use_cache,\n        )\n        return voice_prompt\n\n    audio_paths = []\n    for sample in samples:\n        sample_audio_path = config.resolve_storage_path(sample.audio_path)\n        if sample_audio_path is None:\n            raise ValueError(f\"Sample audio not found for profile {profile_id}\")\n        audio_paths.append(str(sample_audio_path))\n    reference_texts = [s.reference_text for s in samples]\n\n    combined_audio, combined_text = await tts_model.combine_voice_prompts(\n        audio_paths,\n        reference_texts,","sourceCodeStart":567,"sourceCodeEnd":603,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/services/profiles.py#L567-L603","documentation":"Raised in the single-sample path of create_voice_prompt_from_profile() when config.resolve_storage_path(sample.audio_path) returns None. This means the stored audio_path cannot be resolved to a real filesystem location — the underlying file is missing, the storage root is misconfigured, or the stored path is malformed. The function refuses to continue because there is no audio to feed to create_voice_prompt.","triggerScenarios":"The audio file referenced by DBProfileSample.audio_path was deleted from disk (manual cleanup, expired volume); STORAGE_ROOT config changed so resolve_storage_path can no longer locate the file; sample.audio_path stored as an absolute path that no longer exists; file migration that moved assets without updating DB rows.","commonSituations":"Docker volume remount losing uploads; backup restore of DB without restoring the file storage; NFS/object-storage sync lag; dev environment pointing STORAGE_ROOT at a dir missing the assets; CI test using a DB dump without the matching files.","solutions":["Verify the audio file exists on disk at the resolved path and that STORAGE_ROOT is configured correctly.","Re-upload the sample so a valid audio_path is stored and the file lands in the active storage root.","If resolve_storage_path returns None due to a path format issue, normalize sample.audio_path to a storage-relative path.","If files were migrated, run a script to reconcile DBProfileSample.audio_path values with the new storage layout."],"exampleFix":"// before: sample.audio_path points to a file that no longer exists\n// after: re-upload the sample, or fix the storage root\nresolved = config.resolve_storage_path(sample.audio_path)\nif resolved is None or not resolved.exists():\n    raise HTTPException(409, f\"Sample audio missing on disk for sample {sample.id}; re-upload required\")","handlingStrategy":"validation","validationCode":"from backend import config\n\ndef sample_audio_present(sample) -> bool:\n    p = config.resolve_storage_path(sample.audio_path)\n    return p is not None and p.exists()\n\nfor s in db.query(DBProfileSample).filter_by(profile_id=profile_id).all():\n    if not sample_audio_present(s):\n        raise HTTPException(409, f\"Sample {s.id} audio missing on disk\")","typeGuard":null,"tryCatchPattern":"try:\n    prompt = await create_voice_prompt_from_profile(profile_id, db, engine=engine)\nexcept ValueError as e:\n    if 'Sample audio not found' in str(e):\n        raise HTTPException(409, str(e) + ' — re-upload required')\n    raise","preventionTips":["Keep STORAGE_ROOT consistent across all environments sharing the database.","Run a periodic reconciler that flags DBProfileSample rows whose files are missing on disk.","Back up storage volumes alongside the database so restores stay consistent."],"tags":["profiles","samples","storage","filesystem","voicebox"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}