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

  1. Check the preceding log line 'Decoded audio: Xs, YHz, N channels' - zero or absurd values confirm bad metadata
  2. Repair or re-encode the source audio (e.g., ffmpeg -i in.wav out.wav) and retry
  3. 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

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


AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16). Data as JSON: /api/errors/874865a02f7ad13c. Report an issue: GitHub.