{"record":{"id":"5bf1dbd7b715672f","repo":"libnyanpasu/clash-nyanpasu","slug":"failed-to-read-pac-script-content","errorCode":null,"errorMessage":"failed to read PAC script content: {}","messagePattern":"failed to read PAC script content: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/core/pac.rs","lineNumber":43,"sourceCode":"\n    /// Download PAC script from URL with retry logic\n    pub async fn download_pac_script(url: &str) -> Result<String> {\n        let client = reqwest::Client::builder()\n            .timeout(Duration::from_secs(PAC_DOWNLOAD_TIMEOUT))\n            .build()\n            .context(\"failed to build HTTP client\")?;\n\n        // Retry logic\n        let mut last_error = None;\n        for attempt in 1..=PAC_MAX_RETRIES {\n            match client.get(url).send().await {\n                Ok(response) => {\n                    if response.status().is_success() {\n                        match response.text().await {\n                            Ok(content) => return Ok(content),\n                            Err(e) => {\n                                let err =\n                                    anyhow::anyhow!(\"failed to read PAC script content: {}\", e);\n                                log::warn!(target: \"app\", \"Attempt {}/{} failed: {}\", attempt, PAC_MAX_RETRIES, err);\n                                last_error = Some(err);\n                            }\n                        }\n                    } else {\n                        let err = anyhow::anyhow!(\n                            \"failed to download PAC script, status: {}\",\n                            response.status()\n                        );\n                        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                }","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/pac.rs#L25-L61","documentation":"download_pac_script fetches a PAC (Proxy Auto-Config) script over HTTP and reads its body as text. This error is thrown when the HTTP request succeeds with a 2xx status but reading the response body as UTF-8 text fails (network interruption mid-body or invalid UTF-8 content). It is recorded as the last_error and retried up to PAC_MAX_RETRIES times before surfacing.","triggerScenarios":"Calling download_pac_script when response.text().await returns Err — i.e. the connection drops while streaming the body, the body exceeds internal limits, or the bytes are not valid UTF-8.","commonSituations":"Flaky network or proxy dropping the connection mid-download; the PAC URL serves binary/gzip-encoded content instead of plain-text JavaScript; a captive portal returning malformed content.","solutions":["Retry the download — the function already retries automatically; transient body-read failures often resolve","Verify the PAC URL serves plain-text (Content-Type: application/x-ns-proxy-autoconfig) and not compressed/binary content","Check network stability / disable interfering middleboxes or antivirus HTTPS inspection","Fetch the URL with curl to inspect the raw content and confirm it is valid UTF-8 JavaScript","Increase or check the retry count PAC_MAX_RETRIES if the network is persistently unreliable"],"exampleFix":"// before\nOk(content) => return Ok(content),\n// after\nOk(content) => {\n    if content.is_empty() { /* treat as failure and retry */ }\n    return Ok(content);\n}","handlingStrategy":"retry","validationCode":"async fn pac_url_serves_text(url: &str) -> bool {\n    reqwest::get(url).await.map(|r| {\n        r.status().is_success()\n            && r.headers().get(reqwest::header::CONTENT_TYPE)\n                .map(|ct| ct.to_str().map(|s| s.contains(\"text\") || s.contains(\"javascript\")).unwrap_or(false))\n                .unwrap_or(true)\n    }).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match download_pac_script().await {\n    Ok(script) => install(script),\n    Err(e) if e.to_string().contains(\"failed to read PAC script content\") => {\n        log::warn!(\"body read failed ({e}); retrying later or using cached script\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Serve PAC scripts with Content-Type application/x-ns-proxy-autoconfig and no compression the client cannot decode","Monitor the PAC URL with curl for intermittent truncation","Host PAC scripts on reliable infrastructure with keep-alive enabled","Keep a last-known-good cached copy of the script"],"tags":["network","http","pac","proxy"],"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"}