Zackriya-Solutions/meetily · error

Failed to get microphone config: {}

Error message

Failed to get microphone config: {}

What it means

verify_microphone_access opens the default input device and calls default_input_config() via cpal to obtain a stream configuration. If cpal cannot produce a default input configuration for the device, the error is wrapped with anyhow! into this message. It means the device exists but cpal could not negotiate any supported input format.

Source

Thrown at frontend/src-tauri/src/audio/devices/discovery.rs:127

/// audio. Deliberately minimal: it checks the default
/// input device and treats the first callback as "granted" (no sample-content
/// inspection, no per-selected-device check).
pub async fn verify_microphone_access() -> anyhow::Result<()> {
    use log::{info, warn};
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::sync::Arc;

    tokio::task::spawn_blocking(|| {
        let host = cpal::default_host();
        let Some(device) = host.default_input_device() else {
            // Let device resolution handle the existing system-audio-only fallback.
            info!("[verify_microphone_access] No microphone device found; skipping access check");
            return Ok(());
        };

        let config = device
            .default_input_config()
            .map_err(|e| anyhow::anyhow!("Failed to get microphone config: {}", e))?;

        let callback_fired = Arc::new(AtomicBool::new(false));
        let callback_fired_clone = callback_fired.clone();

        let stream = device
            .build_input_stream(
                &config.into(),
                move |_data: &[f32], _: &cpal::InputCallbackInfo| {
                    callback_fired_clone.store(true, Ordering::SeqCst);
                },
                |err| warn!("[verify_microphone_access] test stream error: {}", err),
                None,
            )
            .map_err(|e| anyhow::anyhow!("Cannot access microphone: {}", e))?;

        stream
            .play()
            .map_err(|e| anyhow::anyhow!("Cannot start microphone: {}", e))?;

View on GitHub (pinned to a2cb62e827)

Solutions

  1. Verify the microphone is connected and selected as the OS default input device.
  2. Re-enumerate devices (list_audio_devices) and retry with an explicit valid device instead of the default.
  3. On Linux, check PulseAudio/PipeWire/ALSA configuration (e.g. pactl info, default source).
  4. Update audio drivers (Windows WASAPI) or virtual-device drivers (macOS BlackHole), then restart the app.
Defensive patterns

Strategy: fallback

Try / catch

match verify_microphone_access().await {
    Ok(()) => start_recording(),
    Err(e) if e.to_string().contains("Failed to get microphone config") => {
        // prompt re-enumeration / device reselection
        prompt_device_reselect();
    }
    Err(e) => show_error(e),
}

Prevention

When it happens

Trigger: Calling verify_microphone_access() on a machine where device.default_input_config() returns Err - e.g. no supported sample formats/rates for the selected input device, or the device disappeared between enumeration and config.

Common situations: Microphone unplugged or USB interface powered off mid-session; virtual audio drivers (BlackHole, VB-Cable) with unusual formats; Linux box without proper ALSA/Pulse config; stale default device after OS audio settings change.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@a2cb62e827 (2026-09-12). Data as JSON: /api/errors/d74288ad612b5652. Report an issue: GitHub.