libnyanpasu/clash-nyanpasu · error
failed to read PAC script content: {}
Error message
failed to read PAC script content: {} What it means
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.
Source
Thrown at backend/tauri/src/core/pac.rs:43
/// Download PAC script from URL with retry logic
pub async fn download_pac_script(url: &str) -> Result<String> {
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(PAC_DOWNLOAD_TIMEOUT))
.build()
.context("failed to build HTTP client")?;
// Retry logic
let mut last_error = None;
for attempt in 1..=PAC_MAX_RETRIES {
match client.get(url).send().await {
Ok(response) => {
if response.status().is_success() {
match response.text().await {
Ok(content) => return Ok(content),
Err(e) => {
let err =
anyhow::anyhow!("failed to read PAC script content: {}", e);
log::warn!(target: "app", "Attempt {}/{} failed: {}", attempt, PAC_MAX_RETRIES, err);
last_error = Some(err);
}
}
} else {
let err = anyhow::anyhow!(
"failed to download PAC script, status: {}",
response.status()
);
log::warn!(target: "app", "Attempt {}/{} failed: {}", attempt, PAC_MAX_RETRIES, err);
last_error = Some(err);
}
}
Err(e) => {
let err = anyhow::anyhow!("failed to download PAC script: {}", e);
log::warn!(target: "app", "Attempt {}/{} failed: {}", attempt, PAC_MAX_RETRIES, err);
last_error = Some(err);
}View on GitHub (pinned to f7dbce2997)
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
Example fix
// before
Ok(content) => return Ok(content),
// after
Ok(content) => {
if content.is_empty() { /* treat as failure and retry */ }
return Ok(content);
} Defensive patterns
Strategy: retry
Validate before calling
async fn pac_url_serves_text(url: &str) -> bool {
reqwest::get(url).await.map(|r| {
r.status().is_success()
&& r.headers().get(reqwest::header::CONTENT_TYPE)
.map(|ct| ct.to_str().map(|s| s.contains("text") || s.contains("javascript")).unwrap_or(false))
.unwrap_or(true)
}).unwrap_or(false)
} Try / catch
match download_pac_script().await {
Ok(script) => install(script),
Err(e) if e.to_string().contains("failed to read PAC script content") => {
log::warn!("body read failed ({e}); retrying later or using cached script");
}
Err(e) => return Err(e),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- failed to download PAC script, status: {}
- failed to download PAC script: {}
- failed to download PAC script after {} attempts
- proxy selection succeeded; connection interruption error: {:
- download failed: {e}
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/5bf1dbd7b715672f.
Report an issue: GitHub.