{"record":{"id":"6e4de1df77fa5a23","repo":"gitbutlerapp/gitbutler","slug":"effective-url-is-missing-download","errorCode":null,"errorMessage":"Effective URL is missing","messagePattern":"Effective URL is missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-installer/src/download.rs","lineNumber":43,"sourceCode":"            })\n            .context(\"Failed to set write function\")?;\n\n        transfer\n            .perform()\n            .with_context(|| format!(\"Failed to download from {url}\"))?;\n    }\n\n    let response_code = easy\n        .response_code()\n        .context(\"Failed to get response code\")?;\n    if response_code != 200 {\n        bail!(\"Download of {url} failed with HTTP status: {response_code}\");\n    }\n\n    let effective_url = easy\n        .effective_url()\n        .context(\"Failed to get effective URL\")?\n        .ok_or_else(|| anyhow!(\"Effective URL is missing\"))?;\n\n    crate::release::validate_download_url(effective_url)\n        .with_context(|| format!(\"Download was redirected to an untrusted URL: {effective_url}\"))?;\n\n    String::from_utf8(buf.into_inner()).context(\"Signature file is not valid UTF-8\")\n}\n\npub(crate) fn download_file(url: &str, dest: &Path) -> Result<()> {\n    let mut easy = create_client()?;\n\n    easy.url(url)\n        .with_context(|| format!(\"Failed to set URL: {url}\"))?;\n\n    // Enable libcurl's built-in progress reporting\n    easy.progress(true)?;\n\n    let file = File::create(dest).context(\"Failed to create download file\")?;\n    let file = std::cell::RefCell::new(file);","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-installer/src/download.rs#L25-L61","documentation":"download_to_string() fetches a URL (typically a signature file) with curl and relies on curl's effective_url() to learn the final URL after redirects, for security validation. The error fires when curl followed the request but reports no effective URL (None), which should not normally happen after a successful transfer.","triggerScenarios":"Calling download_and_install_app (which downloads the CLI signature via download_to_string) when the curl easy handle returns Ok(None) for effective_url — e.g. the transfer completed without a recorded final URL due to a curl/transport anomaly.","commonSituations":"Unusual curl versions or proxies that terminate the connection in a way that skips the effective-URL bookkeeping; pathological server responses.","solutions":["Retry the download; this is typically transient transport behavior","Check the curl/libcurl version for known effective_url bugs and upgrade","Verify network/proxy configuration isn't mangling responses"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pre-check reachability and that the URL is https\nlet url_ok = url.starts_with(\"https://\");","typeGuard":null,"tryCatchPattern":"match download_to_string(&sig_url) {\n    Ok(s) => s,\n    Err(e) if e.to_string().contains(\"Effective URL is missing\") => {\n        // transient curl anomaly: retry once with backoff\n        retry_with_backoff(|| download_to_string(&sig_url), 2)?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Use a current curl/libcurl version","Avoid exotic proxy setups that terminate TLS oddly","Retry transient download failures automatically"],"tags":["network","download","curl","redirect"],"backgroundTag":"http-request-failed","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}