Zackriya-Solutions/meetily · warning · anyhow::Error

Retranscription already in progress

Error message

Retranscription already in progress

What it means

start_retranscription serializes batch jobs with a global RAII guard (RetranscriptionGuard over the RETRANSCRIPTION_IN_PROGRESS AtomicBool). The error means another retranscription is currently running in the process; the guard refuses a second concurrent job. The flag is reliably cleared when the first job's guard drops, so this error means a job is genuinely still running (or hung), not leaked.

Source

Thrown at frontend/src-tauri/src/audio/retranscription.rs:99

    RETRANSCRIPTION_IN_PROGRESS.load(Ordering::SeqCst)
}

/// Cancel ongoing retranscription
pub fn cancel_retranscription() {
    RETRANSCRIPTION_CANCELLED.store(true, Ordering::SeqCst);
}

/// Start retranscription of a meeting's audio
pub async fn start_retranscription<R: Runtime>(
    app: AppHandle<R>,
    meeting_id: String,
    meeting_folder_path: String,
    language: Option<String>,
    model: Option<String>,
    provider: Option<String>,
) -> Result<RetranscriptionResult> {
    // Acquire guard - ensures flag is cleared even on panic/early return
    let _guard = RetranscriptionGuard::acquire().map_err(|e| anyhow!(e))?;

    // Reset cancellation flag
    RETRANSCRIPTION_CANCELLED.store(false, Ordering::SeqCst);

    let use_parakeet = provider.as_deref() == Some("parakeet");
    let result = run_retranscription(app.clone(), meeting_id.clone(), meeting_folder_path, language, model, provider).await;

    // Unload the engine after the batch job (success, failure, or cancellation)
    super::common::unload_engine_after_batch(use_parakeet).await;

    // Guard will automatically clear flag on drop
    // No need for manual: RETRANSCRIPTION_IN_PROGRESS.store(false, Ordering::SeqCst);

    match &result {
        Ok(res) => {
            let _ = app.emit(
                "retranscription-complete",
                serde_json::json!({

View on GitHub (pinned to 0281737d87)

Solutions

  1. Check is_retranscription_in_progress_command before starting, and disable the Retranscribe action while true
  2. Cancel the running job first via cancel_retranscription_command, then start the new one
  3. Surface retranscription progress events in the UI so retrying feels unnecessary

Example fix

// before (frontend)
await invoke('start_retranscription', { meetingId, meetingFolderPath });

// after - gate on the in-progress flag
if (await invoke<boolean>('is_retranscription_in_progress')) {
  showToast('Retranscription already running - wait or cancel it first');
  return;
}
await invoke('start_retranscription', { meetingId, meetingFolderPath });
Defensive patterns

Strategy: validation

Validate before calling

// Frontend: refuse to start while a job runs
if (await invoke<boolean>('is_retranscription_in_progress')) {
  showToast('Retranscription already running - cancel it first if needed');
  return;
}
await invoke('start_retranscription', { meetingId, meetingFolderPath });

Try / catch

Catch the 'already in progress' error from start_retranscription and offer two user actions: wait (show existing progress) or cancel (invoke cancel_retranscription_command) then retry once.

Prevention

When it happens

Trigger: Invoking start_retranscription twice (double-click, impatience retry) while the first job is still running; a first job stuck for a long time on decode/VAD/Whisper of a very large meeting file and still holding the guard.

Common situations: Retranscribing a 1-hour-plus meeting where progress appears stalled; user re-clicks Retranscribe because the UI gave no in-progress feedback.

Related errors


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