Zackriya-Solutions/meetily · error · anyhow::Error
Resample task panicked: {}
Error message
Resample task panicked: {} What it means
DecodedAudio::to_whisper_format (conversion to 16 kHz mono) panicked inside its spawn_blocking task, surfacing as a JoinError. The resampler crashed on degenerate decoded-audio parameters - zero channels, zero/absurd sample rate, or malformed sample buffers - rather than handling them as errors.
Source
Thrown at frontend/src-tauri/src/audio/retranscription.rs:225
info!(
"Decoded audio: {:.2}s, {}Hz, {} channels",
duration_seconds, decoded.sample_rate, decoded.channels
);
emit_progress(&app, &meeting_id, "decoding", 15, "Converting audio format...");
// Check for cancellation
if RETRANSCRIPTION_CANCELLED.load(Ordering::SeqCst) {
return Err(anyhow!("Retranscription cancelled"));
}
// Convert to 16kHz mono format (CPU-intensive, run in blocking task)
let audio_samples = tokio::task::spawn_blocking(move || {
decoded.to_whisper_format()
})
.await
.map_err(|e| anyhow!("Resample task panicked: {}", e))?;
info!("Converted to 16kHz mono format: {} samples", audio_samples.len());
emit_progress(&app, &meeting_id, "vad", 20, "Detecting speech segments...");
// Check for cancellation
if RETRANSCRIPTION_CANCELLED.load(Ordering::SeqCst) {
return Err(anyhow!("Retranscription cancelled"));
}
// Use VAD to find natural speech boundaries (same approach as live transcription)
// IMPORTANT: Run VAD in a blocking task to avoid blocking the async runtime
// For large files (35+ minutes), VAD processing can take several minutes
let app_for_vad = app.clone();
let meeting_id_for_vad = meeting_id.clone();
let speech_segments = tokio::task::spawn_blocking(move || {
get_speech_chunks_with_progress(
&audio_samples,View on GitHub (pinned to 0281737d87)
Solutions
- Check the preceding log line 'Decoded audio: Xs, YHz, N channels' - zero or absurd values confirm bad metadata
- Repair or re-encode the source audio (e.g., ffmpeg -i in.wav out.wav) and retry
- Add sanity checks in to_whisper_format so invalid channels/sample_rate return Err instead of panicking
Example fix
// before
// to_whisper_format resamples assuming decoded metadata is valid
// after - reject degenerate metadata before any resample math
if self.channels == 0 || self.sample_rate == 0 {
anyhow::bail!(
"invalid decoded audio: {} channels @ {} Hz - source file is corrupt",
self.channels,
self.sample_rate
);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Post-decode precondition before conversion
if decoded.channels == 0 || decoded.sample_rate == 0 || decoded.samples.is_empty() {
return Err(anyhow::anyhow!("decoded audio is degenerate ({} ch @ {} Hz) - source corrupt", decoded.channels, decoded.sample_rate));
} Try / catch
Treat the JoinError as a data problem, not a transient one: report the source file as corrupt/unsupported and offer re-encode (e.g., ffmpeg) or a different file. Do not auto-retry - the same input will panic again. Log the 'Decoded audio: ...' line for the offending file.
Prevention
- Validate decoded metadata (channels > 0, sample_rate > 0, non-empty samples) before to_whisper_format
- Convert panics to errors inside to_whisper_format instead of letting spawn_blocking surface JoinError
- Keep a fixture corpus of odd-but-valid audio files in tests to catch resampler assumptions
When it happens
Trigger: A file that decodes 'successfully' but to garbage metadata (0 channels or 0 Hz) after corruption; huge sample counts overflowing length arithmetic; channel/index assumptions violated by unusual layouts.
Common situations: Same damaged-file class as decode panics; truncated headers that parse but yield inconsistent stream parameters; files from nonstandard recorders.
Related errors
- Copy task join error: {}
- Decode task join error: {}
- Resample task join error: {}
- Decode task panicked: {}
- VAD task panicked: {}
AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16).
Data as JSON: /api/errors/874865a02f7ad13c.
Report an issue: GitHub.