{"record":{"id":"d7062d1a882c2549","repo":"libnyanpasu/clash-nyanpasu","slug":"download-failed-e","errorCode":null,"errorMessage":"download failed: {e}","messagePattern":"download failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/core/download/mod.rs","lineNumber":133,"sourceCode":"            .build()\n            .await\n            .map_err(|e| anyhow::anyhow!(\"failed to build download task: {e}\"))?;\n        Ok(Self {\n            inner,\n            task: Mutex::new(task),\n        })\n    }\n\n    pub async fn start(&self) -> anyhow::Result<()> {\n        let mut task = self.task.lock().await;\n        task.run()\n            .await\n            .map_err(|e| anyhow::anyhow!(\"failed to start download: {e}\"))?;\n        match task.wait().await {\n            Ok(()) => Ok(()),\n            Err(e) => {\n                *self.inner.state.write() = DownloaderState::Failed(e.to_string());\n                Err(anyhow::anyhow!(\"download failed: {e}\"))\n            }\n        }\n    }\n\n    pub fn status(&self) -> DownloadStatus {\n        let prog = *self.inner.progress.read();\n        DownloadStatus {\n            state: self.inner.state.read().clone(),\n            downloaded: prog.downloaded,\n            total: prog.total,\n            speed: prog.speed,\n        }\n    }\n\n    #[allow(dead_code)]\n    pub fn cancel(&self) {\n        self.inner.cancel.cancel();\n    }","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/download/mod.rs#L115-L151","documentation":"Returned by `DownloadSession::start` when the task was started successfully but `task.wait()` later reports the transfer failed. Before returning, the session's state is set to `DownloaderState::Failed(e.to_string())`, so the failure reason is persisted in `status()` as well. This is the mid-transfer failure path: network errors, server errors, checksum/IO failures during download.","triggerScenarios":"Calling `start()` and the download ultimately fails — HTTP errors from the server (4xx/5xx), connection resets/timeouts, disk full or write error while saving, cancelled-by-remote, or any error surfaced by the download crate's `wait()`.","commonSituations":"Unstable network or VPN drops mid-download; GitHub/CDN returning 403/404/502 for core or geo-data downloads; disk quota exceeded; server closing connection before completion; TLS/proxy interception.","solutions":["Inspect `{e}` and `status()` to learn the failure cause; fix the specific issue (URL, network, disk).","Retry the download with a new session, ideally with backoff for transient network/server errors.","Verify the URL is reachable (curl -I) and the target still exists (core binaries move between releases).","Check free disk space and write permissions on save_path.","If behind a proxy/firewall, configure the reqwest client's proxy settings."],"exampleFix":"// before\nsession.start().await?;\n// after\nmatch session.start().await {\n    Ok(()) => {}\n    Err(e) => {\n        log::warn!(\"download failed: {e:#}, retrying...\");\n        tokio::time::sleep(Duration::from_secs(5)).await;\n        let session = DownloadSession::new(client, url, save_path).await?;\n        session.start().await?;\n    }\n}","handlingStrategy":"retry","validationCode":"// preflight the URL before downloading\nlet head = client.head(url.as_str()).send().await?;\nif !head.status().is_success() {\n    anyhow::bail!(\"URL unreachable: HTTP {}\", head.status());\n}","typeGuard":null,"tryCatchPattern":"match session.start().await {\n    Ok(()) => Ok(()),\n    Err(e) if is_transient(&e) => retry_with_backoff(|| async {\n        DownloadSession::new(client.clone(), url.clone(), save_path.clone()).await?\n            .start().await\n    }),\n    Err(e) => Err(e),\n}","preventionTips":["Retry with a fresh session and exponential backoff for transient network/HTTP errors","Read status().state (Failed carries the reason) before deciding the retry policy","Preflight the URL with a HEAD request; core download URLs change between releases","Check disk space and save-path writability before starting","Configure reqwest proxy/timeouts appropriately for restricted networks"],"tags":["rust","download","network","http"],"backgroundTag":"http-request-failed","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}