{"record":{"id":"1379e7684af909cc","repo":"Zackriya-Solutions/meetily","slug":"failed-to-preserve-during-cancellation","errorCode":null,"errorMessage":"Failed to preserve {} during cancellation: {}","messagePattern":"Failed to preserve (.+?) during cancellation: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"frontend/src-tauri/src/parakeet_engine/parakeet_engine.rs","lineNumber":1002,"sourceCode":"            } else {\n                fs::OpenOptions::new()\n                    .create(true)\n                    .truncate(true)\n                    .write(true)\n                    .open(&file_path)\n                    .await\n                    .map_err(|error| anyhow!(\"Failed to replace {}: {}\", artifact.filename, error))?\n            };\n            let mut writer = BufWriter::with_capacity(8 * 1024 * 1024, file);\n            use futures_util::StreamExt;\n            let mut stream = response.bytes_stream();\n\n            loop {\n                let next_chunk = tokio::select! {\n                    biased;\n                    _ = active_download.cancellation.cancelled() => {\n                        writer.flush().await.map_err(|error| {\n                            anyhow!(\"Failed to preserve {} during cancellation: {}\", artifact.filename, error)\n                        })?;\n                        return Err(DownloadCancelled.into());\n                    }\n                    chunk = timeout(Duration::from_secs(30), stream.next()) => chunk,\n                };\n                let chunk = match next_chunk {\n                    Err(_) => {\n                        writer.flush().await.map_err(|error| {\n                            anyhow!(\"Failed to preserve {} after timeout: {}\", artifact.filename, error)\n                        })?;\n                        return Err(anyhow!(\n                            \"Download timeout for {}: no data received for 30 seconds\",\n                            artifact.filename\n                        ));\n                    }\n                    Ok(None) => break,\n                    Ok(Some(Err(error))) => {\n                        writer.flush().await.map_err(|flush_error| {","sourceCodeStart":984,"sourceCodeEnd":1020,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/a2cb62e827da7ef59f65064c97233efb2313878e/frontend/src-tauri/src/parakeet_engine/parakeet_engine.rs#L984-L1020","documentation":"Raised inside the download loop when the user/UI cancels an active Parakeet model download (`active_download.cancellation.cancelled()` fires). Before returning `DownloadCancelled`, the code attempts one final `writer.flush()` so already-buffered bytes are persisted for later resume; if that flush itself fails on the file handle, this error is thrown instead and masks the cancellation with a flush failure. It is a secondary error on top of an intentional cancellation.","triggerScenarios":"The download's CancellationToken is cancelled while the BufWriter still holds up to 8 MB of buffered bytes, and the final flush hits an I/O error: file handle became invalid, disk full, medium removed (USB/network drive unplugged), permission revoked mid-download, or the file was deleted/locked by another process during the download.","commonSituations":"User closes the app or clicks Cancel while the model is mid-download and the disk is already full from the partial write; the models folder lives on an external/network drive that dropped; antivirus locks the partial file at the moment of cancel; crash of the underlying storage during a large multi-GB model download.","solutions":["Fix the root I/O cause reported after the second `{}` — usually disk-full: free space or point the models directory at a drive with room for the full artifact size.","If the models dir is on removable/network storage, move it to local disk (app data dir) so cancellation flushes reliably.","Check that no other process deleted or locked the partial file during download; exclude the models dir from antivirus scanning.","Retry the download after cleanup — the code is designed to resume from a preserved partial file, so once flush works the retry appends cleanly.","If this error frequently hides real cancellations, consider logging flush failures non-fatally during cancellation so `DownloadCancelled` propagates."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before cancelling, confirm the partial file is on healthy storage\nlet meta = tokio::fs::metadata(&partial_path).await\n    .map_err(|e| format!(\"partial file inaccessible, resume may fail: {e}\"))?;\nif free_space(&partial_path)? < min_free_bytes {\n    return Err(\"insufficient disk space to preserve partial download\".into());\n}","typeGuard":null,"tryCatchPattern":"match engine.download_models(&artifacts, &token).await {\n    Err(e) if e.to_string().contains(\"during cancellation\") => {\n        log::warn!(\"cancellation flush failed; discarding partial: {e}\");\n        let _ = tokio::fs::remove_file(&partial_path).await; // start clean next time\n    }\n    Err(DownloadCancelledError) => { /* normal cancel path */ }\n    other => other?,\n}","preventionTips":["Keep the models directory on healthy local disk with headroom for the full artifact size","Avoid cancelling during the final large flush window; cancel between artifacts when the UI allows","Exclude the models dir from antivirus real-time scanning so the partial file is never locked","Treat 'Failed to preserve ... during cancellation' as disk-full/storage-unplugged first"],"tags":["filesystem","flush","cancellation","model-download","rust"],"backgroundTag":"file-write-failed","analyzedSha":"a2cb62e827da7ef59f65064c97233efb2313878e","analyzedAt":"2026-09-12T11:12:14.152Z","contentChangedAt":"2026-09-12T11:12:14.152Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}