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
- Read the HTTP status in the message: 404 → fix the URL, 403/401 → fix auth, 5xx → wait/fix server
- Verify the PAC URL in the app config is correct and reachable (open it in a browser or curl it)
- Re-upload or restore the PAC script on the web server if it was removed
- Check whether a corporate/ISP proxy intercepts and rejects the request
- 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
- Verify the PAC URL returns 200 before configuring it in the app
- Pin PAC scripts to stable URLs with redirects handled server-side
- Add server-side monitoring/uptime checks for the PAC endpoint
- Avoid URLs behind expiring tokens or auth walls
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
- failed to read PAC script content: {}
- 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/9259ff445effd759.
Report an issue: GitHub.