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

  1. Retry the download — the function already retries automatically; transient body-read failures often resolve
  2. Verify the PAC URL serves plain-text (Content-Type: application/x-ns-proxy-autoconfig) and not compressed/binary content
  3. Check network stability / disable interfering middleboxes or antivirus HTTPS inspection
  4. Fetch the URL with curl to inspect the raw content and confirm it is valid UTF-8 JavaScript
  5. 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

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


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/5bf1dbd7b715672f. Report an issue: GitHub.