{"record":{"id":"eca8044ef7838813","repo":"libnyanpasu/clash-nyanpasu","slug":"failed-to-download-pac-script-after-attempts","errorCode":null,"errorMessage":"failed to download PAC script after {} attempts","messagePattern":"failed to download PAC script after (.+?) attempts","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/core/pac.rs","lineNumber":71,"sourceCode":"                        log::warn!(target: \"app\", \"Attempt {}/{} failed: {}\", attempt, PAC_MAX_RETRIES, err);\n                        last_error = Some(err);\n                    }\n                }\n                Err(e) => {\n                    let err = anyhow::anyhow!(\"failed to download PAC script: {}\", e);\n                    log::warn!(target: \"app\", \"Attempt {}/{} failed: {}\", attempt, PAC_MAX_RETRIES, err);\n                    last_error = Some(err);\n                }\n            }\n\n            // Wait before retrying (except on last attempt)\n            if attempt < PAC_MAX_RETRIES {\n                tokio::time::sleep(Duration::from_secs(PAC_RETRY_DELAY)).await;\n            }\n        }\n\n        Err(last_error.unwrap_or_else(|| {\n            anyhow::anyhow!(\n                \"failed to download PAC script after {} attempts\",\n                PAC_MAX_RETRIES\n            )\n        }))\n    }\n\n    /// Save PAC script to cache directory\n    pub async fn save_pac_script(script: &str) -> Result<PathBuf> {\n        let cache_dir = crate::utils::dirs::cache_dir()?;\n        let pac_file = cache_dir.join(\"pac.js\");\n\n        fs::write(&pac_file, script)\n            .await\n            .context(\"failed to save PAC script\")?;\n\n        Ok(pac_file)\n    }\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/pac.rs#L53-L89","documentation":"This is the terminal error returned by download_pac_script after all PAC_MAX_RETRIES attempts have failed. It wraps the last underlying error (last_error); if that is somehow None it is produced standalone. It signals that no retry remains and the caller must handle PAC unavailability.","triggerScenarios":"Calling download_pac_script when every attempt fails with transport errors, non-2xx statuses, or body-read failures — after PAC_MAX_RETRIES attempts separated by PAC_RETRY_DELAY seconds.","commonSituations":"Prolonged server outage or network disconnection during startup; permanently wrong PAC URL; server blocking the client; offline laptop starting the app with no connectivity.","solutions":["Inspect the wrapped cause (last_error) printed in earlier 'Attempt N/M failed' warnings to find the root cause","Fix the underlying network/URL problem identified in the wrapped error","Ensure the app's fallback path (fallback_to_direct_proxy) runs so the system proxy still works","Increase PAC_MAX_RETRIES or PAC_RETRY_DELAY for unreliable networks","Cache a previously downloaded PAC script locally and use it when download fails"],"exampleFix":"// caller-side handling\nmatch Pac::download_pac_script().await {\n    Ok(script) => { /* install script */ }\n    Err(e) => {\n        log::warn!(\"PAC unavailable: {e}; falling back to direct proxy\");\n        Pac::fallback_to_direct_proxy()?;\n    }\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"match download_pac_script().await {\n    Ok(script) => install(script),\n    Err(e) => {\n        log::warn!(\"PAC unavailable after retries: {e}; falling back to direct proxy\");\n        fallback_to_direct_proxy().unwrap_or_else(|fe| log::error!(\"no system proxy either: {fe}\"));\n    }\n}","preventionTips":["Always implement a fallback proxy mode when PAC download fails","Cache the last successful PAC script and use it offline","Increase retry count/delay for mobile or flaky networks","Alert on repeated download failures so the URL gets fixed"],"tags":["network","retry","pac","proxy","timeout"],"backgroundTag":"request-timeout","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"}