{"record":{"id":"4a3ae13565c5bb28","repo":"gitbutlerapp/gitbutler","slug":"no-app-bundle-found-in-extracted-archive","errorCode":null,"errorMessage":"No .app bundle found in extracted archive","messagePattern":"No \\.app bundle found in extracted archive","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-installer/src/install_macos.rs","lineNumber":333,"sourceCode":"    let file = File::open(tarball)?;\n    let decoder = GzDecoder::new(file);\n    let mut archive = Archive::new(decoder);\n    archive\n        .unpack(dest_dir)\n        .context(\"Failed to extract archive\")?;\n\n    // Find the extracted .app bundle\n    let mut app_dir = None;\n    for entry in fs::read_dir(dest_dir)? {\n        let entry = entry?;\n        let path = entry.path();\n        if path.is_dir() && path.extension().and_then(|s| s.to_str()) == Some(\"app\") {\n            app_dir = Some(path);\n            break;\n        }\n    }\n\n    app_dir.ok_or_else(|| anyhow!(\"No .app bundle found in extracted archive\"))\n}\n\npub(crate) fn verify_app_structure(app_dir: &Path) -> Result<()> {\n    let binaries_dir = app_dir.join(\"Contents/MacOS\");\n    if !binaries_dir.is_dir() {\n        bail!(\n            \"Extracted app bundle does not contain expected directory structure (Contents/MacOS)\"\n        );\n    }\n\n    let required_binaries = [\"gitbutler-git-askpass\", \"gitbutler-tauri\"];\n\n    for binary in &required_binaries {\n        let binary_path = binaries_dir.join(binary);\n        if !binary_path.exists() {\n            bail!(\"Missing required binary: {binary}\");\n        }\n    }","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-installer/src/install_macos.rs#L315-L351","documentation":"Thrown by extract_tarball in install_macos.rs after unpacking the release tarball: it scans the extraction directory for a directory whose extension is \"app\" and found none. The archive downloaded and extracted fine, but its layout does not contain the expected top-level .app bundle that verify_app_structure and install_app require.","triggerScenarios":"A release archive with a changed layout (bundle nested deeper, different naming, or zipped rather than a plain tarball); a tampered or corrupted archive that extracted into unexpected paths; a proxy serving an HTML error page that happened to decompress as an empty tar.","commonSituations":"A new release packaging change the installer version does not understand; installing an old installer against a future release format; CDN or proxy interference mangling the artifact.","solutions":["Manually download and inspect the tarball (tar -tf <tarball>) to see what it actually contains at the top level.","Update the but-installer/but CLI to a version matching the release format you are installing.","Re-download the archive to rule out corruption, and confirm verify_signature and validate_tarball passed on the same file.","If the official archive genuinely lacks the bundle, report it to GitButler with the release version."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// After extraction, check for the expected bundle before the installer does\nfn find_app_bundle(dest: &std::path::Path) -> Option<std::path::PathBuf> {\n    std::fs::read_dir(dest).ok()?.flatten().map(|e| e.path()).find(|p| {\n        p.is_dir() && p.extension().and_then(|s| s.to_str()) == Some(\"app\")\n    })\n}","typeGuard":null,"tryCatchPattern":"match extract_tarball(&tarball_path, temp_dir.path()) {\n    Ok(app_dir) => { /* verify + install */ },\n    Err(e) if e.to_string().contains(\"No .app bundle\") => {\n        // re-download or switch to a release with the expected layout\n    },\n    Err(e) => return Err(e),\n}","preventionTips":["Keep the installer version in sync with the release format you install.","Inspect tar -tf output when automating installs against new channels.","Verify signature and tarball validation passed — they usually catch corrupted archives before this stage."],"tags":["installer","macos","tarball","app-bundle","archive-layout"],"backgroundTag":"archive-extraction-failed","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}