libnyanpasu/clash-nyanpasu · error

failed to download PAC script, status: {}

Error message

failed to download PAC script, status: {}

What it means

download_pac_script checks response.status().is_success() before reading the body; this error is thrown when the server responds with a non-2xx HTTP status (404, 403, 500, etc.). The status code is embedded in the message, and the error is retried up to PAC_MAX_RETRIES before being returned as last_error.

Source

Thrown at backend/tauri/src/core/pac.rs:49

            .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);
                }
            }

            // Wait before retrying (except on last attempt)
            if attempt < PAC_MAX_RETRIES {
                tokio::time::sleep(Duration::from_secs(PAC_RETRY_DELAY)).await;
            }

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Read the HTTP status in the message: 404 → fix the URL, 403/401 → fix auth, 5xx → wait/fix server
  2. Verify the PAC URL in the app config is correct and reachable (open it in a browser or curl it)
  3. Re-upload or restore the PAC script on the web server if it was removed
  4. Check whether a corporate/ISP proxy intercepts and rejects the request
  5. If the server is temporarily down, rely on the built-in retries or fix the URL to a stable mirror

Example fix

// before
let pac_url = "http://old-server/proxy.pac";
// after
let pac_url = "https://new-server/proxy.pac"; // verify with curl -I before configuring
Defensive patterns

Strategy: retry

Validate before calling

async fn pac_url_ok(url: &str) -> Result<(), String> {
    let resp = reqwest::get(url).await.map_err(|e| e.to_string())?;
    if resp.status().is_success() { Ok(()) } else { Err(format!("status {}", resp.status())) }
}

Try / catch

match download_pac_script().await {
    Ok(script) => install(script),
    Err(e) if e.to_string().contains("status: 404") => log::error!("PAC script missing on server; fix URL"),
    Err(e) => log::warn!("PAC download failed: {e}"),
}

Prevention

When it happens

Trigger: Calling download_pac_script when the configured PAC URL returns a non-success HTTP status — e.g. the script was deleted from the server (404), auth is required (401/403), or the server errors (5xx).

Common situations: PAC URL points to a moved/removed script; misconfigured web server or CDN returning errors; corporate proxy rejecting the request; server-side outage producing 5xx responses.

Related errors


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