jdx/mise · error

build of {name} finished but produced no keg at {}

Error message

build of {name} finished but produced no keg at {}

What it means

After running the Homebrew source build, mise expects the resulting keg (install prefix directory) to exist under the Cellar. If the build command reported success but the keg directory is missing, the outcome is inconsistent with Homebrew's contract, so mise removes any partial state and surfaces this error.

Source

Thrown at src/system/packages/brew/source.rs:151

    pr.set_message("build from source".to_string());
    let cmd = CmdLineRunner::new(&ruby)
        .arg(&shim_path)
        .current_dir(&buildpath)
        .envs(build_env(
            rf,
            closure,
            &pkg_version,
            &buildpath,
            &formula_rb,
        ))
        .with_pr(pr);
    let built = cmd.execute_async().await;
    if let Err(err) = built {
        let _ = crate::file::remove_all(&keg);
        return Err(err.wrap_err(format!("failed to build {name} {pkg_version} from source")));
    }
    if !keg.is_dir() {
        bail!(
            "build of {name} finished but produced no keg at {}",
            keg.display()
        );
    }

    let host_tag = tag::host_tag();
    let receipt = pour::write_receipt(
        rf,
        &host_tag,
        &keg,
        &Default::default(),
        closure,
        /* poured_from_bottle */ false,
    );
    let linked = receipt.and_then(|()| pour::link_keg(name, &pkg_version, formula.keg_only));
    if let Err(err) = linked {
        if let Err(rm_err) = crate::file::remove_all(&keg) {
            warn!(

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Re-run the build with verbose logging (MISE_DEBUG=1) to see what the build actually installed
  2. Check that HOMEBREW_PREFIX/Cellar is not overridden or relocated during the build
  3. Verify the formula's install block actually creates its prefix under Cellar
  4. Install via bottle or another mise backend instead of source

Example fix

// before: formula with silent install
install []
// after
install ["bin/foo"]
prefix.install "bin/foo"
Defensive patterns

Strategy: try-catch

Validate before calling

// after build, before proceeding
if !keg.is_dir() { eprintln!("build produced no keg; inspect build logs"); }

Try / catch

match build_formula(&formula).await {
    Err(e) if e.to_string().contains("produced no keg") => {
        // clean partial state and retry with verbose logging / bottle fallback
    }
    other => other?,
}

Prevention

When it happens

Trigger: `build` executes the brew/build command which exits 0, but `keg.is_dir()` is false — e.g. a custom post-build step relocated output, the build wrote to a different Cellar prefix, or the formula's install stage silently did nothing.

Common situations: Formulas with broken/empty install blocks; running with an overridden HOMEBREW_PREFIX mid-build; wrappers that fake success; disk cleanup scripts deleting the Cellar during the build.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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