{"record":{"id":"1b8fe53e909d0e92","repo":"jdx/mise","slug":"download-cancelled-by-user","errorCode":null,"errorMessage":"download cancelled by user","messagePattern":"download cancelled by user","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/http.rs","lineNumber":1232,"sourceCode":"            }\n\n            if let Some(pr) = pr {\n                if let Some(total_size) = total_size {\n                    pr.set_length(total_size);\n                }\n                pr.set_position(write_offset);\n            }\n            let mut file = tokio::fs::OpenOptions::new()\n                .create(true)\n                .write(true)\n                .append(write_offset > 0)\n                .truncate(write_offset == 0)\n                .open(&partial.path)\n                .await?;\n            let transfer = async {\n                while let Some(chunk) = resp.chunk().await? {\n                    if crate::ui::ctrlc::is_cancelled() {\n                        bail!(\"download cancelled by user\");\n                    }\n                    file.write_all(&chunk).await?;\n                    bytes_received.fetch_add(chunk.len() as u64, Ordering::Relaxed);\n                    if let Some(pr) = pr {\n                        pr.inc(chunk.len() as u64);\n                    }\n                }\n                Ok::<_, Report>(())\n            }\n            .await;\n            // Outside the transfer, so it also runs when the transfer failed.\n            // `tokio::fs::File` buffers writes and dropping one does not flush,\n            // so a transfer that dies part way through was leaving the bytes it\n            // had already received unwritten — the resume then asked for a range\n            // starting before them and downloaded them again. Whether any of it\n            // survived depended on when the background flush happened to land.\n            let persisted = async {\n                file.shutdown().await?;","sourceCodeStart":1214,"sourceCodeEnd":1250,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/http.rs#L1214-L1250","documentation":"Raised when the user presses Ctrl-C (or otherwise signals cancellation) while an HTTP download body is being streamed to a partial file. The download loop checks a global cancellation flag before writing each chunk and aborts with this error. The partial file is truncated if nothing had been written yet, so resumable downloads can continue from the written offset on retry.","triggerScenarios":"User hits Ctrl-C during `mise install`/backend HTTP download while `resp.chunk()` streaming is in progress and `crate::ui::ctrlc::is_cancelled()` returns true.","commonSituations":"Developer interrupts a slow tool download (large Node/Python archives, slow network) mid-transfer; CI job timeout sends SIGINT to mise.","solutions":["Re-run the install command; partial downloads resume from the written offset","Check network speed/stability if cancellations are accidental (timeouts prompting manual aborts)","In CI, increase job timeout or pre-install tools in a cached layer to avoid long-running downloads","Use a mirror or faster network (`MISE_...` mirror settings) if downloads regularly need interrupting"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// resumable download: just retry the install\nif err.contains(\"download cancelled by user\") {\n    // partial file kept at write_offset; re-running resumes\n    retry_install();\n}","preventionTips":["Pre-install tools in cached CI layers so downloads are not interrupted by job timeouts","Avoid Ctrl-C during installs; let mise handle resume on the next run","Use mirrors for large downloads to shorten transfer windows"],"tags":["network","download","cancellation","http"],"backgroundTag":"user-cancelled-operation","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}