jdx/mise · error
brew bottles are only published for a formula's current…
Error message
brew bottles are only published for a formula's current version ('{p}'): pin via the formula name instead (e.g. "brew:postgresql@17") What it means
mise's brew backend pours prebuilt Homebrew bottles, which exist only for a formula's currently-published version. Pinned versions like `brew:postgresql=17.2` cannot be satisfied by a bottle, so install_via_pour refuses the request and tells you to encode the version in the formula name itself (versioned formulae such as postgresql@17). The CLI is documented to filter pinned requests out before this point, so reaching this error means a pinned request slipped through.
Solutions
- Remove the version pin and use the versioned formula name instead: `brew:postgresql@17` rather than `brew:postgresql=17`
- Check how the request reached the backend — the CLI should filter pinned brew requests out, so a direct API/scripted caller must do the filtering itself
- If you truly need an exact old version not offered as a @-formula, install it with plain `brew` outside mise or use a different backend (e.g. github:, cargo:)
Example fix
// before [bootstrap.packages] "brew:postgresql" = "17.2" // after [bootstrap.packages] "brew:postgresql@17" = "*"
Defensive patterns
Strategy: validation
Validate before calling
const pinned = pkgs.filter(p => p.version != null);
if (pinned.length > 0) {
throw new Error(`brew requests must not pin versions: ${pinned.map(p => p.name).join(', ')} — use versioned formula names like postgresql@17`);
} Type guard
const isUnpinned = (p) => p.version == null; const brewPkgs = pkgs.filter(isUnpinned);
Prevention
- Always express brew versions via @-formulae (node@20, postgresql@17), never version pins
- Route brew package requests through the mise CLI, which filters pinned requests before the backend
- Review [bootstrap.packages] entries for `brew:name=version` syntax after migrations
When it happens
Trigger: Calling the brew package install/upgrade path (install_via_pour, invoked by install and upgrade) with a PackageRequest whose version field is Some — e.g. `mise bootstrap packages apply` or package install with `brew:foo=1.2.3` syntax that bypassed the CLI's pinned-request filter.
Common situations: Writing brew packages directly into mise.toml `[bootstrap.packages]` with an `=` version; scripting against the backend API instead of the CLI; older configs migrated from another tool that used version-pinned brew syntax.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- brew casks are installed at their current version
- app Info.plist must be a regular file
- app target is outside an allowed Applications directory
- apt-cache not found
- artifact target has changed
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/69b87bcfedc90290.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/mod.rs:124
for request in pkgs {
let name = request_formula_name(&request.name);
let state = linked_package_state(&request.version, pour::linked_state(name));
if matches!(state, PackageState::NeedsRepair { .. })
&& pour::repair_link_record(name, opts.dry_run)?
{
repaired.push(request.clone());
}
}
Ok(repaired)
}
/// Prefetch bottles concurrently, then install the closure in dependency order.
async fn install_via_pour(&self, pkgs: &[PackageRequest], opts: &InstallOpts) -> Result<()> {
// bottles only exist for a formula's current version — versioning is
// expressed in the formula name itself (postgresql@17); the CLI
// filters pinned requests out before calling
if let Some(p) = pkgs.iter().find(|p| p.version.is_some()) {
bail!(
"brew bottles are only published for a formula's current version ('{p}'): \
pin via the formula name instead (e.g. \"brew:postgresql@17\")"
);
}
let roots: Vec<String> = pkgs.iter().map(|p| p.name.clone()).collect();
let closure = resolve::resolve_closure_with_taps(pkgs, !opts.dry_run).await?;
for rf in &closure {
if rf.on_request
&& !roots.contains(&rf.formula.name)
&& let Some(alias) = roots.iter().find(|r| rf.formula.aliases.contains(r))
{
warn!(
"'{alias}' is an alias of '{}' — use the canonical name in [bootstrap.packages] \
so `mise bootstrap packages status` can track it",
rf.formula.name
);
}
}View on GitHub (pinned to 533346cc37)