{"record":{"id":"dcdae722fab56b48","repo":"jamiepine/voicebox","slug":"invalid-reference-audio-error-msg","errorCode":null,"errorMessage":"Invalid reference audio: {error_msg}","messagePattern":"Invalid reference audio: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/services/profiles.py","lineNumber":229,"sourceCode":"        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,\n        audio_path=config.to_storage_path(dest_path),\n        reference_text=reference_text,\n    )\n\n    db.add(db_sample)\n\n    profile.updated_at = datetime.utcnow()","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/services/profiles.py#L211-L247","documentation":"Raised by add_profile_sample() when validate_and_load_reference_audio() rejects the uploaded audio. The wrapped error_msg is one of: 'Audio too short (minimum 2.0 seconds)', 'Audio too long (maximum 30.0 seconds)', 'Audio is too quiet or silent', or 'Error validating audio: {load exception}'. Duration/silence checks run on the preprocessed waveform, so slight clipping is tolerated but genuinely silent or out-of-range audio is rejected.","triggerScenarios":"Uploading a clip shorter than 2s or longer than 30s; an essentially silent track (RMS below 0.01 after preprocessing); a corrupt or unreadable file; an unsupported container/codec that load_audio cannot decode.","commonSituations":"User records a very short snippet; uploads background music or a near-empty track; file truncated during transfer; wrong file sent (e.g. a .wav header on a non-audio payload); ffmpeg/backend decoder missing for the codec.","solutions":["Trim/record the clip to between 2 and 30 seconds of clean speech.","Re-export from the source at a standard format (WAV/MP3) and confirm it plays back with audible volume.","Inspect the specific error_msg: 'too short'/'too long'/'too quiet' point to content; 'Error validating audio' points to decoding — re-encode the file or install the missing decoder."],"exampleFix":"# before - 1s silent clip uploaded\n# after - export a 5-15s clean speech wav\nffmpeg -i in.mp3 -t 10 -ar 24000 -ac 1 out.wav","handlingStrategy":"validation","validationCode":"from ..utils.audio import validate_and_load_reference_audio\n\n# pre-check the file before calling add_profile_sample\nok, msg, _audio, _sr = validate_and_load_reference_audio(audio_path)\nif not ok:\n    raise HTTPException(400, f\"reference audio rejected: {msg}\")\n# duration limits: 2.0s..30.0s, RMS >= 0.01 after preprocessing","typeGuard":"import os\n\ndef is_likely_valid_audio(path: str) -> bool:\n    return os.path.exists(path) and os.path.getsize(path) > 0 and path.lower().endswith((\".wav\", \".mp3\", \".flac\", \".ogg\", \".m4a\"))","tryCatchPattern":"try:\n    await add_profile_sample(profile_id, audio_path, ref_text, db)\nexcept ValueError as e:\n    if str(e).startswith(\"Invalid reference audio\"):\n        raise HTTPException(400, str(e))  # surface the specific reason to the client\n    raise","preventionTips":["Record/export 5-15s of clean speech at a normal volume.","Run validate_and_load_reference_audio on the uploaded temp file before persisting.","On 'too quiet', re-record; on 'Error validating audio', re-encode the file (e.g. ffmpeg) or install the missing decoder."],"tags":["profiles","samples","audio","validation","create"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}