cjpais/Handy · error

Failed to create AudioRecorder: {}

Error message

Failed to create AudioRecorder: {}

What it means

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.

Source

Thrown at src-tauri/src/managers/audio.rs:284

    stream_router: Arc<StreamRouter>,
) -> Result<AudioRecorder, anyhow::Error> {
    // A single Silero engine covers both the offline and streaming policies (never
    // active at once within a recording), so the recorder reconfigures its
    // hangover tail per session rather than keeping two ONNX sessions resident.
    let silero = SileroVad::new(vad_path, VAD_THRESHOLD)
        .map_err(|e| anyhow::anyhow!("Failed to create SileroVad: {}", e))?;
    let smoothed_vad = SmoothedVad::new(
        Box::new(silero),
        VAD_PREFILL_FRAMES,
        VAD_OFFLINE_HANGOVER_FRAMES,
        VAD_ONSET_FRAMES,
    );

    // Recorder with VAD, a spectrum-level callback that forwards level updates to
    // the frontend, and an audio-frame callback that feeds live streaming via a
    // shared `StreamRouter` (captured directly, not via Tauri state — see its docs).
    let recorder = AudioRecorder::new()
        .map_err(|e| anyhow::anyhow!("Failed to create AudioRecorder: {}", e))?
        .with_vad(
            Box::new(smoothed_vad),
            VAD_OFFLINE_HANGOVER_FRAMES,
            VAD_STREAMING_HANGOVER_FRAMES,
        )
        .with_selected_channel(selected_channel)
        .with_level_callback({
            let app_handle = app_handle.clone();
            move |levels| {
                utils::emit_levels(&app_handle, &levels);
            }
        })
        .with_audio_callback({
            let router = stream_router;
            move |frame| {
                router.feed(frame);
            }
        });

View on GitHub (pinned to 98a4d80cce)

Solutions

  1. Inspect the {e} payload — it identifies whatever fallible step the constructor now performs
  2. If seen with the current code, treat it as a bug: file it against the constructor contract rather than the environment
  3. Check system resources (threads/memory) if the constructor spawns a worker
Defensive patterns

Strategy: try-catch

Try / catch

let recorder = AudioRecorder::new()
    .map_err(|e| anyhow::anyhow!("AudioRecorder init failed: {e}"))?;

Prevention

When it happens

Trigger: 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.

Common situations: Future refactors that move cpal host/device queries into new(); a failed thread spawn under thread/memory exhaustion; effectively unreachable in the shipped code.

Related errors


AI-assisted analysis of cjpais/Handy@98a4d80cce (2026-08-16). Data as JSON: /api/errors/332dc37fcbbede3d. Report an issue: GitHub.