{"record":{"id":"2ce0e95ba8dd26de","repo":"jamiepine/voicebox","slug":"audio-file-not-found-audio-path","errorCode":null,"errorMessage":"Audio file not found: {audio_path}","messagePattern":"Audio file not found: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/services/export_import.py","lineNumber":108,"sourceCode":"            },\n            \"has_avatar\": has_avatar,\n        }\n        zip_file.writestr(\"manifest.json\", json.dumps(manifest, indent=2))\n\n        # Create samples.json mapping\n        samples_data = {}\n        profile_dir = config.get_profiles_dir() / profile_id\n\n        for sample in samples:\n            # Get filename from audio_path (should be {sample_id}.wav)\n            audio_path = config.resolve_storage_path(sample.audio_path)\n            if audio_path is None:\n                raise ValueError(f\"Audio file not found: {sample.audio_path}\")\n            filename = audio_path.name\n\n            # Read audio file\n            if not audio_path.exists():\n                raise ValueError(f\"Audio file not found: {audio_path}\")\n\n            # Add to samples directory in ZIP\n            zip_path = f\"samples/{filename}\"\n            zip_file.write(audio_path, zip_path)\n\n            # Map filename to reference text\n            samples_data[filename] = sample.reference_text\n\n        zip_file.writestr(\"samples.json\", json.dumps(samples_data, indent=2))\n    \n    zip_buffer.seek(0)\n    return zip_buffer.read()\n\n\nasync def import_profile_from_zip(file_bytes: bytes, db: Session) -> VoiceProfileResponse:\n    \"\"\"\n    Import a voice profile from a ZIP archive.\n    ","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/services/export_import.py#L90-L126","documentation":"resolve_storage_path() returned a real Path but that file does not exist() on disk. Distinct from error 231 (un-resolvable path): here the path resolves but the bytes are gone. The message uses the resolved Path so the operator knows where the file was expected.","triggerScenarios":"Sample file deleted/moved from disk while the DB row remains; backup restored the DB but not the audio; filesystem permissions making exists() return False.","commonSituations":"Manual cleanup of the profiles directory; antivirus quarantining .wav files; partial disk failure; sync tool that didn't pull audio files.","solutions":["Restore the missing .wav from backup to the resolved path.","If unrecoverable, delete the orphaned DBProfileSample row and re-record.","Check filesystem permissions on the profiles directory."],"exampleFix":"# before\nif not audio_path.exists():\n    raise ValueError(f\"Audio file not found: {audio_path}\")\n\n# after — skip missing with a warning rather than failing the whole export\nif not audio_path.exists():\n    logger.warning(\"missing sample %s for profile %s; skipping\", audio_path, profile_id)\n    continue","handlingStrategy":"validation","validationCode":"from backend import config\nfrom backend.database import ProfileSample as DBProfileSample\n\ndef all_sample_files_present(profile_id, db) -> bool:\n    for s in db.query(DBProfileSample).filter_by(profile_id=profile_id):\n        p = config.resolve_storage_path(s.audio_path)\n        if p is None or not p.exists():\n            return False\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    data = export_profile_to_zip(pid, db)\nexcept ValueError as e:\n    if \"Audio file not found\" in str(e):\n        # prompt user to repair/re-record the missing sample\n        ...\n    raise","preventionTips":["Back up the profiles directory alongside the DB.","Don't manually delete audio files without removing the DB row.","Periodically reconcile DBProfileSample rows against disk."],"tags":["profiles","export","storage","missing-file","data-integrity"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}