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
- Re-run the build with verbose logging (MISE_DEBUG=1) to see what the build actually installed
- Check that HOMEBREW_PREFIX/Cellar is not overridden or relocated during the build
- Verify the formula's install block actually creates its prefix under Cellar
- 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
- Don't override HOMEBREW_PREFIX/Cellar during builds
- Watch for formulas with empty install blocks
- Run builds with MISE_DEBUG=1 to catch silent no-op installs
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
- {} install path does not exist: {}. Run `mise install` first
- brew casks are installed at their current version ('{p}')
- brew-cask:{}: dependency cycle detected
- brew-cask:{}: Homebrew owns this cask; remove it with Homebr
- brew-cask:{}: conflicts with installed cask {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/06dddc7cbe78d289.
Report an issue: GitHub.