jdx/mise · error

unexpected bottle layout for {name}: missing {name}/{pkg_ver

Error message

unexpected bottle layout for {name}: missing {name}/{pkg_version} in archive

What it means

After extracting a downloaded Homebrew bottle tarball, pour expects the standard layout <name>/<pkg_version>/ inside the archive and moves that directory into the keg. If the expected directory is absent, the bottle's layout is unrecognized, so it aborts rather than installing a mangled package.

Source

Thrown at src/system/packages/brew/pour.rs:227

    }
    crate::file::create_dir_all(&scratch)?;

    // bottle tarballs contain <name>/<pkg_version>/...
    pr.set_message("extract".to_string());
    crate::file::untar(
        tarball,
        &scratch,
        ExtractionFormat::TarGz,
        &ExtractOptions {
            strip_components: 0,
            pr: Some(pr),
            preserve_mtime: true,
        },
    )
    .wrap_err_with(|| format!("failed to extract bottle for {name}"))?;
    let inner = scratch.join(name).join(&pkg_version);
    if !inner.exists() {
        bail!("unexpected bottle layout for {name}: missing {name}/{pkg_version} in archive");
    }
    crate::file::rename(&inner, &tmp)?;
    crate::file::remove_all(&scratch)?;

    // ":any_skip_relocation" skips binary linkage relocation, but Homebrew
    // still replaces placeholders in text files. On Linux, bottles built by
    // Homebrew < 5.1.15 are incorrectly tagged and still need ELF linkage
    // relocation (brew applies the same version check in
    // extend/os/linux/bottle_specification.rb).
    let skip_linkage = bottle.cellar == ":any_skip_relocation"
        && (cfg!(target_os = "macos") || bottled_by_homebrew_at_least(&tmp, (5, 1, 15)));
    pr.set_message("relocate".to_string());
    let report = relocate::relocate_keg(&tmp, name, skip_linkage)?;
    // arm64 macOS kills binaries whose signature doesn't match; Linux ELF
    // files have no signatures to fix
    if cfg!(target_os = "macos") && !report.changed_machos.is_empty() {
        pr.set_message("codesign".to_string());
        relocate::codesign(&report.changed_machos)

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Delete the cached/downloaded bottle and re-run so it downloads fresh
  2. Verify the bottle tarball layout with `tar tf <bottle>.tar.gz` — expect `<name>/<version>/`
  3. Check disk space and network integrity; retry the install
  4. Report the formula if upstream publishes a non-standard bottle layout
Defensive patterns

Strategy: retry

Validate before calling

# verify bottle layout before/after download
 tar tzf bottle.tar.gz | grep -q '^<name>/<version>/' || echo 'unexpected bottle layout'

Try / catch

catch (e) {
  if (String(e).includes('unexpected bottle layout')) {
    purgeBottleCache();
    return retryInstall();
  }
  throw e;
}

Prevention

When it happens

Trigger: The downloaded bottle tarball does not contain a top-level `<name>/<pkg_version>/` directory — e.g. a corrupt/truncated download, a bottle built with an unexpected layout, or a mismatch between the requested version and the bottle contents.

Common situations: Proxy or CDN serving an HTML error page saved as a tarball; manually crafted or third-party bottles; Homebrew changing tab/layout details; interrupted download left a partial cache entry.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/7ca4f252efa1c740. Report an issue: GitHub.