jdx/mise · error · RuntimeError
could not infer formula version; add an explicit version dec
Error message
could not infer formula version; add an explicit version declaration
What it means
mise extracts the stable version of a formula from an explicit `version ...` declaration, or falls back to heuristically parsing the version out of the source URL basename (inferred_version). If neither yields a version — no explicit version declaration and the URL's filename doesn't match the version regex — this raise fires, instructing the formula author to add an explicit version declaration.
Source
Thrown at src/system/packages/brew/tap_formula_metadata.rb:220
def test(*) = nil
def method_missing(*) = nil
def respond_to_missing?(*) = true
end
end
def inferred_version(url)
basename = File.basename(url.to_s).sub(/\.(tar\.(gz|xz|bz2|zst)|tgz|txz|zip|gz)\z/i, "")
match = basename.match(/(?:^|[-_v])([0-9]+(?:\.[0-9A-Za-z]+)+(?:[-_.][0-9A-Za-z]+)*)/)
match && match[1]
end
eval(STDIN.read.force_encoding("UTF-8"), TOPLEVEL_BINDING, FORMULA_FILE, 1)
klass = Formula.instance_variable_get(:@subclass)
raise "no Formula subclass found" unless klass
raise "formula has no stable URL" if klass.source_url.to_s.empty?
raise "formula has no stable sha256" if klass.source_sha256.to_s.empty?
version = (klass.explicit_version || inferred_version(klass.source_url)).to_s
raise "could not infer formula version; add an explicit version declaration" if version.to_s.empty?
metadata = {
"name" => FORMULA_NAME,
"tap" => ENV.fetch("MISE_BREW_TAP"),
"versions" => { "stable" => version },
"revision" => klass.revision_value || 0,
"keg_only" => klass.keg_only_value || false,
"dependencies" => klass.runtime_dependencies || [],
"build_dependencies" => klass.build_dependencies || [],
"bottle" => {},
"urls" => { "stable" => { "url" => klass.source_url, "checksum" => klass.source_sha256 } },
"ruby_source_path" => ENV.fetch("MISE_BREW_SOURCE_PATH"),
"ruby_source_checksum" => { "sha256" => ENV.fetch("MISE_BREW_SOURCE_CHECKSUM") },
"tap_git_head" => ENV.fetch("MISE_BREW_TAP_COMMIT")
}
puts JSON.generate(metadata)
View on GitHub (pinned to afd2eddd3a)
Solutions
- Add an explicit `version "1.2.3"` declaration to the formula's stable spec (most reliable fix)
- Use a versioned download URL whose basename contains the dotted version (e.g. foo-1.2.3.tar.gz)
- Point the url at a stable versioned release asset instead of latest/main archive endpoints
- Check the basename against the extractor's regex `(?:^|[-_v])([0-9]+(\.[0-9A-Za-z]+)+...)` and adjust the artifact naming
Example fix
// before // class Foo < Formula // url "https://example.com/releases/latest/download/foo.tgz" // sha256 "abc..." // end // after // class Foo < Formula // version "1.2.3" // url "https://example.com/releases/download/1.2.3/foo.tgz" // sha256 "abc..." // end
Defensive patterns
Strategy: validation
Validate before calling
url = File.read(formula_path)[/^\s*url\s+["']([^"']+)["']/, 1]
version = File.read(formula_path)[/^\s*version\s+["']([^"']+)["']/, 1]
version ||= url.to_s.split("/").last.sub(/\.(tar\.(gz|xz|bz2|zst)|tgz|txz|zip|gz)\z/i, "")[/(?:^|[-_v])([0-9]+(?:\.[0-9A-Za-z]+)+)/, 1]
raise "cannot determine formula version" if version.to_s.empty? Type guard
def version_inferable?(formula_source) return true if formula_source.match?(/^\s*version\s+["']/) url = formula_source[/^\s*url\s+["']([^"']+)["']/, 1].to_s basename = File.basename(url).sub(/\.(tar\.(gz|xz|bz2|zst)|tgz|txz|zip|gz)\z/i, "") !basename.match(/(?:^|[-_v])([0-9]+(?:\.[0-9A-Za-z]+)+)/).nil? end
Try / catch
begin
extract_formula_metadata(formula_path)
rescue RuntimeError => e
raise unless e.message.include?("could not infer formula version")
warn "Add an explicit `version` declaration to #{formula_path} or use a versioned URL"
end Prevention
- Always include an explicit `version "x.y.z"` when authoring or pinning formulas
- Avoid latest/main archive URLs (releases/latest/download, archive/refs/heads/main.tar.gz) that carry no version
- Use download URLs whose filename contains a dotted version token
- Verify the URL basename matches the extractor's version regex before adding the formula
When it happens
Trigger: Formula lacks `version "x.y.z"` and its url basename has no recognizable version token (regex requires digit-led dotted segments after start or a [-_v] separator); url points at a repo archive like `main.tar.gz`, `latest.zip`, or `releases/current/download/foo.tgz`; url basename has only a single undotted number (e.g. `foo-2.tar.gz`) which fails the multi-segment pattern.
Common situations: GitHub `archive/refs/heads/main.tar.gz` or `releases/latest/download/...` URLs used by third-party taps; download URLs with opaque names (`foo-nightly.tgz`, `foo.tar.gz?param=1`); formulas relying on Homebrew's automatic version inference from the url where mise's simpler regex can't; renamed artifacts without version substrings.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- no Formula subclass found
- formula has no stable URL
- formula has no stable sha256
- no version specified for tool {tool}\nuse `mise shell {tool}
- brew casks are installed at their current version ('{p}')
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/c5ee82361df77b6a.
Report an issue: GitHub.