Kuberwastaken/claurst · error · anyhow::Error
No input device available
Error message
No input device available
What it means
record_audio asks cpal's default host for the default input device; when none exists it returns this error before any stream setup. The library cannot capture audio without a device, so it fails immediately with a clear message.
Solutions
- Connect or enable a microphone/input device.
- Start the system audio server (pipewire/pulseaudio) on Linux.
- Check availability() or enumerate input devices before attempting recording and show a friendly message.
- On Linux, install ALSA/PipeWire dev runtime libs so cpal's host can find devices.
Example fix
// before
let text = voice.record_and_transcribe().await?;
// after
if cpal::default_host().default_input_device().is_none() {
eprintln!("no microphone detected; voice input disabled");
return Ok(());
}
let text = voice.record_and_transcribe().await?; Defensive patterns
Strategy: fallback
Validate before calling
fn has_input_device() -> bool {
cpal::default_host().default_input_device().is_some()
} Try / catch
match voice.record_and_transcribe().await {
Ok(t) => t,
Err(e) if e.to_string().contains("No input device") => {
eprintln!("no microphone; falling back to typed input");
typed_input()?
}
Err(e) => return Err(e),
} Prevention
- Enumerate input devices at startup; disable voice if empty.
- On Linux verify PipeWire/PulseAudio is running before recording.
- Provide a non-voice fallback input path.
When it happens
Trigger: record_audio running on a machine where cpal::default_host().default_input_device() returns None — no microphone, no audio subsystem, or audio daemon not running.
Common situations: Headless servers/containers with no sound hardware; SSH sessions without PulseAudio/PipeWire; VM with no audio passthrough; microphone disabled at BIOS/OS level; PulseAudio not started.
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 Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/74ed127a48a5f2f4.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/core/src/voice.rs:396
}
}
// ---------------------------------------------------------------------------
// Audio capture (cpal, feature-gated)
// ---------------------------------------------------------------------------
#[cfg(feature = "voice")]
async fn record_audio(
is_recording: Arc<AtomicBool>,
event_tx: mpsc::Sender<VoiceEvent>,
) -> anyhow::Result<(Vec<f32>, u32)> {
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use std::time::Duration;
let host = cpal::default_host();
let device = host
.default_input_device()
.ok_or_else(|| anyhow::anyhow!("No input device available"))?;
let supported_config = device.default_input_config()?;
let sample_rate = supported_config.sample_rate().0;
let channels = supported_config.channels() as usize;
let samples: Arc<Mutex<Vec<f32>>> = Arc::new(Mutex::new(Vec::new()));
let samples_clone = samples.clone();
let err_tx = event_tx.clone();
let is_recording_for_err = is_recording.clone();
let stream = {
let config: cpal::StreamConfig = supported_config.into();
device.build_input_stream(
&config,
move |data: &[f32], _: &cpal::InputCallbackInfo| {
// Mix down to mono if needed
let mut s = samples_clone.lock().unwrap();
if channels == 1 {
View on GitHub (pinned to b0637c97ec)