{"record":{"id":"b2c2c13eed53f71f","repo":"Zackriya-Solutions/meetily","slug":"retranscription-cancelled","errorCode":null,"errorMessage":"Retranscription cancelled","messagePattern":"Retranscription cancelled","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"info","filePath":"frontend/src-tauri/src/audio/retranscription.rs","lineNumber":196,"sourceCode":"    provider: Option<String>,\n) -> Result<RetranscriptionResult> {\n    let folder_path = PathBuf::from(&meeting_folder_path);\n    let audio_path = find_audio_file(&folder_path)?;\n\n    // Determine which provider to use (default to whisper)\n    let use_parakeet = provider.as_deref() == Some(\"parakeet\");\n\n    info!(\n        \"Starting retranscription for meeting {} with language {:?}, model {:?}, provider {:?}\",\n        meeting_id, language, model, provider\n    );\n\n    // Emit progress: decoding\n    emit_progress(&app, &meeting_id, \"decoding\", 5, \"Decoding audio file...\");\n\n    // Check for cancellation\n    if RETRANSCRIPTION_CANCELLED.load(Ordering::SeqCst) {\n        return Err(anyhow!(\"Retranscription cancelled\"));\n    }\n\n    // Decode the audio file (CPU-intensive, run in blocking task)\n    let path_for_decode = audio_path.clone();\n    let decoded = tokio::task::spawn_blocking(move || {\n        decode_audio_file(&path_for_decode)\n    })\n    .await\n    .map_err(|e| anyhow!(\"Decode task panicked: {}\", e))??;\n    let duration_seconds = decoded.duration_seconds;\n\n    info!(\n        \"Decoded audio: {:.2}s, {}Hz, {} channels\",\n        duration_seconds, decoded.sample_rate, decoded.channels\n    );\n\n    emit_progress(&app, &meeting_id, \"decoding\", 15, \"Converting audio format...\");\n","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src-tauri/src/audio/retranscription.rs#L178-L214","documentation":"Cooperative cancellation checkpoint: before the CPU-heavy decode stage, run_retranscription checks the RETRANSCRIPTION_CANCELLED AtomicBool and bails out if the user cancelled. The flag is set only by cancel_retranscription and reset at job start, so this error always reflects an intentional cancel, not a malfunction.","triggerScenarios":"User clicks Cancel (cancel_retranscription_command) while a retranscription job is between the 'decoding' progress emission and the spawn_blocking decode call.","commonSituations":"Cancelling a long retranscription of a long meeting because the wrong meeting, language, or model was chosen.","solutions":["Treat this as expected control flow: show 'Cancelled' in the UI, not an error","Restart the retranscription if the cancellation was accidental","Emit a terminal cancelled progress event so the UI resets its state cleanly"],"exampleFix":"// before\nlet result = run_retranscription(app, meeting_id, folder, lang, model, provider).await?;\n\n// after - branch on cancellation so it is not surfaced as a failure\nmatch run_retranscription(app, meeting_id, folder, lang, model, provider).await {\n    Ok(result) => Ok(result),\n    Err(e) if e.to_string().contains(\"cancelled\") => {\n        emit_progress(&app, &meeting_id, \"cancelled\", 0, \"Cancelled by user\");\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"In the retranscription result handler, branch on the error message: 'Retranscription cancelled' maps to a neutral 'Cancelled' UI state (no error toast, reset progress), all other errors map to failure with retry option.","preventionTips":["Model cancellation as a distinct result state, not an error, in UI state machines","Reset RETRANSCRIPTION_CANCELLED only via start_retranscription so flags stay coherent","Emit a terminal 'cancelled' progress event so listeners can clean up"],"tags":["cancellation","retranscription","user-cancel","cooperative-cancel"],"backgroundTag":"operation-cancelled","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}