{"record":{"id":"06dddc7cbe78d289","repo":"jdx/mise","slug":"build-of-name-finished-but-produced-no-keg-at","errorCode":null,"errorMessage":"build of {name} finished but produced no keg at {}","messagePattern":"build of (.+?) finished but produced no keg at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/source.rs","lineNumber":151,"sourceCode":"    pr.set_message(\"build from source\".to_string());\n    let cmd = CmdLineRunner::new(&ruby)\n        .arg(&shim_path)\n        .current_dir(&buildpath)\n        .envs(build_env(\n            rf,\n            closure,\n            &pkg_version,\n            &buildpath,\n            &formula_rb,\n        ))\n        .with_pr(pr);\n    let built = cmd.execute_async().await;\n    if let Err(err) = built {\n        let _ = crate::file::remove_all(&keg);\n        return Err(err.wrap_err(format!(\"failed to build {name} {pkg_version} from source\")));\n    }\n    if !keg.is_dir() {\n        bail!(\n            \"build of {name} finished but produced no keg at {}\",\n            keg.display()\n        );\n    }\n\n    let host_tag = tag::host_tag();\n    let receipt = pour::write_receipt(\n        rf,\n        &host_tag,\n        &keg,\n        &Default::default(),\n        closure,\n        /* poured_from_bottle */ false,\n    );\n    let linked = receipt.and_then(|()| pour::link_keg(name, &pkg_version, formula.keg_only));\n    if let Err(err) = linked {\n        if let Err(rm_err) = crate::file::remove_all(&keg) {\n            warn!(","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/source.rs#L133-L169","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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"],"exampleFix":"// before: formula with silent install\ninstall []\n// after\ninstall [\"bin/foo\"]\nprefix.install \"bin/foo\"","handlingStrategy":"try-catch","validationCode":"// after build, before proceeding\nif !keg.is_dir() { eprintln!(\"build produced no keg; inspect build logs\"); }","typeGuard":null,"tryCatchPattern":"match build_formula(&formula).await {\n    Err(e) if e.to_string().contains(\"produced no keg\") => {\n        // clean partial state and retry with verbose logging / bottle fallback\n    }\n    other => other?,\n}","preventionTips":["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"],"tags":["homebrew","build","cellar"],"backgroundTag":"internal-invariant-violation","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}