screenpipe/screenpipe · error
mlx transcription panic (likely Metal GPU error): {}
Error message
mlx transcription panic (likely Metal GPU error): {} What it means
The MLX (Apple Silicon) transcription engine catches panics from spawned transcription tasks via catch_unwind and records that the model likely crashed due to a Metal GPU error. The `{}` is filled with the panic message; this is raised inside `transcribe` as it retries/falls back (called by `transcribe_detailed`).
Source
Thrown at crates/screenpipe-audio/src/transcription/engine.rs:852
}));
mlx_memory::clear_cache();
match outcome {
Ok(Ok(result)) => {
had_success = true;
let text = result.text.trim().to_string();
if !text.is_empty() {
texts.push(text);
}
}
Ok(Err(e)) => last_err = Some(anyhow!("{}", e)),
Err(panic) => {
let msg = panic
.downcast_ref::<String>()
.map(|s| s.as_str())
.or_else(|| panic.downcast_ref::<&str>().copied())
.unwrap_or("unknown panic");
last_err = Some(anyhow!(
"mlx transcription panic (likely Metal GPU error): {}",
msg
));
}
}
}
// Any successful chunk yields a (possibly partial) transcript rather
// than discarding the whole batch. Only error if every chunk failed.
if had_success {
Ok(texts.join(" "))
} else {
Err(last_err.unwrap_or_else(|| anyhow!("mlx transcription produced no output")))
}
}
Self::Whisper {
state,
languages,View on GitHub (pinned to 4ebf712990)
Solutions
- Retry with a smaller model (e.g. large -> small/base) to reduce VRAM/unified-memory pressure
- Chunk long audio into shorter segments before transcription
- Close GPU-heavy apps or reboot to free Metal memory
- Update macOS and the mlx crates; fall back to a non-MLX (CPU/ONNX) engine if configured
Example fix
// before
let result = mlx_engine.transcribe(&audio).await?;
// after
let result = match mlx_engine.transcribe(&audio).await {
Ok(r) => Ok(r),
Err(e) if e.to_string().contains("Metal") => cpu_engine.transcribe(&audio).await,
Err(e) => Err(e),
}; Defensive patterns
Strategy: fallback
Validate before calling
if audio_samples.len() > MAX_CHUNK { chunk audio before calling transcribe } Try / catch
match engine.transcribe(audio).await { Ok(r) => r, Err(e) => fallback_engine.transcribe(audio).await? } Prevention
- Use a smaller MLX model when memory is constrained
- Chunk long recordings instead of one large transcription
- Keep GPU memory headroom; close heavy Metal apps
- Pin updated mlx crates and macOS versions
When it happens
Trigger: Running Whisper-family models via MLX when the Metal device hits an out-of-memory condition, an unsupported operation, or a driver-level assert inside the mlx-rs crate.
Common situations: Long audio files exhausting GPU memory; other apps holding Metal resources; older macOS/GPU combos; model too large for available unified memory.
Related errors
- each collection slot filled
- at least 2 chunks
- eval decoder layer
- save_file task panicked: {}
- portal capture task panicked: {e}
AI-assisted analysis of screenpipe/screenpipe@4ebf712990 (2026-09-01).
Data as JSON: /api/errors/0fe75b66f548f525.
Report an issue: GitHub.