{"record":{"id":"3060d58255a79885","repo":"gitbutlerapp/gitbutler","slug":"download-failed-the-download-artifact-could-not-be-found","errorCode":null,"errorMessage":"Download failed, the download artifact could not be found. Most likely, the but CLI has not been published for the requested version.","messagePattern":"Download failed, the download artifact could not be found\\. Most likely, the but CLI has not been published for the requested version\\.","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"crates/but-installer/src/download.rs","lineNumber":125,"sourceCode":"        // Check if we had a write error\n        if let Some(io_err) = write_error.borrow_mut().take() {\n            // Clear progress line before showing error\n            crate::ui::println_empty();\n            return Err(io_err).context(\"Failed to write downloaded data\");\n        }\n\n        // If perform failed for other reasons, propagate that error\n        perform_result.with_context(|| format!(\"Failed to download from {url}\"))?;\n    }\n\n    // Clear progress line\n    crate::ui::println_empty();\n\n    let response_code = easy\n        .response_code()\n        .context(\"Failed to get response code\")?;\n    if response_code == 403 {\n        bail!(\n            \"Download failed, the download artifact could not be found. Most likely, the but CLI has not been published for the requested version.\"\n        )\n    } else if response_code != 200 {\n        bail!(\"Download failed with HTTP status: {response_code}\");\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    crate::release::validate_download_url(effective_url)\n        .with_context(|| format!(\"Download was redirected to an untrusted URL: {effective_url}\"))?;\n\n    Ok(())\n}","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-installer/src/download.rs#L107-L143","documentation":"`download_file` treats HTTP 403 from the release/download server as a special case: the artifact simply is not there for the requested version. It bails with this explicit message rather than a generic HTTP error, because GitButler's artifact host returns 403 (not 404) for missing files.","triggerScenarios":"Calling download_and_install_app for a version whose platform artifact was never uploaded — e.g. `but upgrade` to a brand-new release before CI finished publishing, an unpublished/typo'd version string, or a platform (like linux-aarch64) excluded from that release.","commonSituations":"Upgrading immediately after a release announcement before artifacts propagate; pinning a specific old/new version that lacks your platform's build; corporate proxies rewriting 404s into 403s.","solutions":["Verify the requested version is actually published (check the release on the GitButler releases page / latest.json).","Retry later — artifacts may still be uploading for a fresh release.","Omit the version pin and install/upgrade to the latest published version.","Check whether your platform's artifact exists for that specific release; if not, build from source."],"exampleFix":"// before\nlet cfg = Config::new_with_version(os, arch, VersionReq::parse(\"0.9.0\")?, ...)?;\ndownload_and_install_app(&cfg)?;\n// after\nlet cfg = Config::new_with_version(os, arch, \"latest\".parse()?, ...)?; // or retry later\ndownload_and_install_app(&cfg)?;","handlingStrategy":"fallback","validationCode":"let status = reqwest::blocking::Client::new()\n    .head(&artifact_url).send()?.status();\nif status.as_u16() == 403 {\n    anyhow::bail!(\"artifact for version {} not published yet\", version);\n}","typeGuard":null,"tryCatchPattern":"match download_and_install_app(&config) {\n    Err(e) if e.to_string().contains(\"has not been published\") => {\n        eprintln!(\"version not available; falling back to latest\");\n        download_and_install_app(&Config::new_with_version(os, arch, \"latest\".parse()?, ...)?)?;\n    }\n    r => r?,\n}","preventionTips":["Don't pin brand-new versions immediately after release; wait for artifacts to propagate.","Check the release's published assets (per-platform) before requesting a specific version+platform.","For automated upgrades, fall back to 'latest' when a pinned version is unavailable."],"tags":["http","download","versioning","artifact-missing"],"backgroundTag":"upstream-api-error","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"}