Zackriya-Solutions/meetily · error

Cannot start microphone: {}

Error message

Cannot start microphone: {}

What it means

If the input stream was built successfully, verify_microphone_access calls stream.play() to start it. A failure there is wrapped as 'Cannot start microphone: {}'. The stream exists but the audio backend refused to start delivering callbacks.

Source

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

            .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))?;

        // Wait up to 5s for the first callback.
        for _ in 0..50 {
            if callback_fired.load(Ordering::SeqCst) {
                drop(stream);
                info!("[verify_microphone_access] microphone access verified");
                return Ok(());
            }
            std::thread::sleep(std::time::Duration::from_millis(100));
        }

        drop(stream);
        Err(anyhow::anyhow!(
            "Microphone permission not granted. Please allow microphone access in \
             System Settings > Privacy & Security > Microphone, then try again."
        ))
    })
    .await

View on GitHub (pinned to a2cb62e827)

Solutions

  1. Retry the verification - transient start failures often clear on the second attempt.
  2. Reconnect/reselect the microphone and re-run device enumeration first.
  3. Catch this in the caller and prompt the user to pick another input device.
  4. Update audio drivers if it reproduces with a specific device.
Defensive patterns

Strategy: retry

Try / catch

for attempt in 0..2 {
    match verify_microphone_access().await {
        Ok(()) => break,
        Err(e) if e.to_string().contains("Cannot start microphone") && attempt == 0 => continue,
        Err(e) => { show_error(e); break; }
    }
}

Prevention

When it happens

Trigger: stream.play() returning Err after a successful build_input_stream - backend could not start the device (device became unavailable between build and play, driver error, invalid state).

Common situations: Device unplugged in the milliseconds between stream creation and play; driver crash/reset during stream start; macOS device invalidated by OS (sleep/wake, sample-rate change by another app).

Related errors


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