{"record":{"id":"35f318022926275e","repo":"gitbutlerapp/gitbutler","slug":"no-download-url-for-platform-in-release-35f318","errorCode":null,"errorMessage":"No download URL for platform {} in release {}","messagePattern":"No download URL for platform (.+?) in release (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-installer/src/install_macos.rs","lineNumber":31,"sourceCode":"use flate2::read::GzDecoder;\nuse tar::Archive;\n\nuse crate::{\n    config::{Channel, InstallerConfig},\n    download::download_file,\n    install::{validate_installed_binary, verify_signature},\n    release::{PlatformInfo, Release, validate_download_url},\n    ui::{info, success, warn},\n};\n\npub fn download_and_install_app(\n    config: &InstallerConfig,\n    platform_info: &PlatformInfo,\n    release: &Release,\n    channel: Option<Channel>,\n) -> Result<()> {\n    let download_url = platform_info.url.as_deref().ok_or_else(|| {\n        anyhow::anyhow!(\n            \"No download URL for platform {} in release {}\",\n            config.platform,\n            release.version\n        )\n    })?;\n\n    validate_download_url(download_url)?;\n    info(&format!(\"Download URL: {download_url}\"));\n\n    let temp_dir = tempfile::Builder::new()\n        .prefix(\"gitbutler-install.\")\n        .tempdir()?;\n\n    let filename = download_url\n        .split('/')\n        .next_back()\n        .ok_or_else(|| anyhow::anyhow!(\"Failed to extract filename from download URL\"))?;\n    let tarball_path = temp_dir.path().join(filename);","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-installer/src/install_macos.rs#L13-L49","documentation":"macOS counterpart of the Linux error, thrown in download_and_install_app in crates/but-installer/src/install_macos.rs when PlatformInfo.url is None for config.platform. The release metadata entry for the platform exists but has no .tar.gz download URL, so the installer cannot proceed to validate_download_url or download the tarball.","triggerScenarios":"Installing a release whose platforms entry for the macOS platform key (e.g. \"macos\") has a null url; requesting a release that predates macOS tarball publishing; API response no longer populating the url field.","commonSituations":"Installing an old pinned release without macOS artifacts; running under Rosetta or an arch variant whose platform key resolved to an entry with no artifact; an incomplete release published to the API.","solutions":["Install the latest release or nightly channel, which always carries the macOS tarball URL.","Verify the release JSON: the entry under release.platforms[config.platform] must have a non-null url.","Check which platform key was detected (config.platform) and confirm it matches the key the release actually uses.","If the latest release is also missing the artifact, report it — it is a publishing-side gap."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before calling download_and_install_app on macOS\nif platform_info.url.is_none() {\n    eprintln!(\"release {} has no macOS tarball; try latest\", release.version);\n    return Ok(());\n}","typeGuard":"fn has_download_url(p: &PlatformInfo) -> bool {\n    p.url.as_deref().map(|u| !u.is_empty()).unwrap_or(false)\n}","tryCatchPattern":"match download_and_install_app(&config, platform_info, &release, channel) {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"No download URL for platform\") => {\n        // re-fetch with VersionRequest::Release and retry\n    },\n    Err(e) => return Err(e),\n}","preventionTips":["Pin automated installs to the latest release rather than old versions.","Check the release JSON's platform entry has a non-null url before invoking the installer.","Surface release.version in failure logs for quick artifact-gap diagnosis."],"tags":["installer","macos","tarball","release-metadata","download-url"],"backgroundTag":"missing-platform-artifact","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}