{"record":{"id":"332dc37fcbbede3d","repo":"cjpais/Handy","slug":"failed-to-create-audiorecorder","errorCode":null,"errorMessage":"Failed to create AudioRecorder: {}","messagePattern":"Failed to create AudioRecorder: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/managers/audio.rs","lineNumber":284,"sourceCode":"    stream_router: Arc<StreamRouter>,\n) -> Result<AudioRecorder, anyhow::Error> {\n    // A single Silero engine covers both the offline and streaming policies (never\n    // active at once within a recording), so the recorder reconfigures its\n    // hangover tail per session rather than keeping two ONNX sessions resident.\n    let silero = SileroVad::new(vad_path, VAD_THRESHOLD)\n        .map_err(|e| anyhow::anyhow!(\"Failed to create SileroVad: {}\", e))?;\n    let smoothed_vad = SmoothedVad::new(\n        Box::new(silero),\n        VAD_PREFILL_FRAMES,\n        VAD_OFFLINE_HANGOVER_FRAMES,\n        VAD_ONSET_FRAMES,\n    );\n\n    // Recorder with VAD, a spectrum-level callback that forwards level updates to\n    // the frontend, and an audio-frame callback that feeds live streaming via a\n    // shared `StreamRouter` (captured directly, not via Tauri state — see its docs).\n    let recorder = AudioRecorder::new()\n        .map_err(|e| anyhow::anyhow!(\"Failed to create AudioRecorder: {}\", e))?\n        .with_vad(\n            Box::new(smoothed_vad),\n            VAD_OFFLINE_HANGOVER_FRAMES,\n            VAD_STREAMING_HANGOVER_FRAMES,\n        )\n        .with_selected_channel(selected_channel)\n        .with_level_callback({\n            let app_handle = app_handle.clone();\n            move |levels| {\n                utils::emit_levels(&app_handle, &levels);\n            }\n        })\n        .with_audio_callback({\n            let router = stream_router;\n            move |frame| {\n                router.feed(frame);\n            }\n        });","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/cjpais/Handy/blob/98a4d80cce8ad41efec2a419b59d9e81229a35d7/src-tauri/src/managers/audio.rs#L266-L302","documentation":"Wraps AudioRecorder::new() in create_audio_recorder (audio.rs:284). Note: in the current code the constructor is effectively infallible — recorder.rs:92-103 only builds the struct and returns Ok(()) — so this error is a defensive guard that should not fire today. If it ever fires, the constructor has gained fallible work (host enumeration, worker thread spawn) and {e} holds that cause.","triggerScenarios":"Calling create_audio_recorder after AudioRecorder::new was changed to do fallible initialization (e.g. enumerating the cpal host or spawning the audio worker thread fails). With the present implementation there is no runtime condition that produces it.","commonSituations":"Future refactors that move cpal host/device queries into new(); a failed thread spawn under thread/memory exhaustion; effectively unreachable in the shipped code.","solutions":["Inspect the {e} payload — it identifies whatever fallible step the constructor now performs","If seen with the current code, treat it as a bug: file it against the constructor contract rather than the environment","Check system resources (threads/memory) if the constructor spawns a worker"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let recorder = AudioRecorder::new()\n    .map_err(|e| anyhow::anyhow!(\"AudioRecorder init failed: {e}\"))?;","preventionTips":["Keep AudioRecorder::new infallible (pure construction) so this guard stays dead code","If the constructor gains fallible steps, move them to explicit fallible methods callers can handle separately"],"tags":["rust","audio","cpal","constructor","defensive-code"],"backgroundTag":"audio-recorder-init-failed","analyzedSha":"98a4d80cce8ad41efec2a419b59d9e81229a35d7","analyzedAt":"2026-08-16T20:58:09.966Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}