{"record":{"id":"3086de33e2a75cdd","repo":"gitbutlerapp/gitbutler","slug":"effective-url-is-missing","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/release.rs","lineNumber":71,"sourceCode":"                bail!(\n                    \"Failed to fetch release information for version {version}. Version may not exist. HTTP {response_code}\"\n                );\n            }\n            crate::config::VersionRequest::Nightly => {\n                bail!(\"Failed to fetch nightly release information. HTTP {response_code}\");\n            }\n            crate::config::VersionRequest::Release => {\n                bail!(\"Failed to fetch release information from {url}. HTTP {response_code}\");\n            }\n        }\n    }\n\n    // Validate the effective URL after following redirects\n    // This protects against malicious redirects to untrusted domains or insecure protocols\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    validate_api_url(effective_url).with_context(|| {\n        format!(\"Release API was redirected to an untrusted URL: {effective_url}\")\n    })?;\n\n    let release: Release =\n        serde_json::from_slice(&response_data).context(\"Failed to parse release information\")?;\n\n    // Verify we got the version we requested (skip check for nightly)\n    if let crate::config::VersionRequest::Specific(ref requested) = config.version_request\n        && release.version != requested.as_str()\n    {\n        bail!(\n            \"API returned version {} but requested version {}\",\n            release.version,\n            requested\n        );\n    }","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-installer/src/release.rs#L53-L89","documentation":"Thrown in release.rs after the libcurl transfer when easy.effective_url() returns Ok(None). libcurl always records the final URL after following redirects, so a None here means the curl handle state is abnormal (transfer not completed on this handle, an unusual libcurl build, or an interrupted transfer). It guards the redirect-validation step that checks the API was not redirected off app.gitbutler.com.","triggerScenarios":"A libcurl/libcurl-sys version that does not populate CURLINFO_EFFECTIVE_URL after the performed request; the transfer being reset or the handle reused abnormally between perform and query; exotic TLS/proxy middleboxes breaking the transfer's completion state.","commonSituations":"Systems with unusual or outdated libcurl builds (some minimal distros, containers with old curl); almost never seen on standard setups — treat as an environment/toolchain defect rather than a GitButler-side problem.","solutions":["Update libcurl on the system (and rebuild but-installer so libcurl-sys links the new version).","Check for HTTP_PROXY/HTTPS_PROXY interference and retry without the proxy.","Retry the command — a one-off None can follow an interrupted transfer.","Report to GitButler with your libcurl version if it persists on a current curl."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match fetch_release(&config) {\n    Ok(r) if std::env::var(\"GB_SKIP_REDIRECT_CHECK\").is_err() => Ok(r),\n    Ok(r) => Ok(r),\n    Err(e) if e.to_string().contains(\"Effective URL is missing\") => {\n        // environment defect: verify libcurl version, then retry once\n        Err(e)\n    },\n    Err(e) => Err(e),\n}","preventionTips":["Keep system libcurl current on hosts running the installer.","Rule out proxies that interrupt transfers before blaming the API.","Capture the libcurl version in bug reports for this error."],"tags":["installer","curl","redirect","url-validation"],"backgroundTag":"redirect-validation-failed","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}