jdx/mise · error · RuntimeError
cask has no version
Error message
cask has no version
What it means
`tap_cask_metadata.rb` parses a cask file in a minimal sandboxed DSL and collects fields into a hash via `to_h`. A cask without a `version` stanza is incomplete/invalid, so `to_h` raises 'cask has no version' rather than emitting a hash with a null version. This guards the metadata generation pipeline from publishing unusable cask records.
Source
Thrown at src/system/packages/brew/tap_cask_metadata.rb:250
when :or_older then host <= target || host.same_release?(target)
when :or_newer then host >= target
else host.same_release?(target)
end
end
private :macos_condition_matches?
def name(*) = nil
def desc(*) = nil
def homepage(*) = nil
def livecheck(*) = nil
def caveats(*) = nil
def container(*) = nil
def deprecate!(**) = nil
def disable!(**) = nil
def no_autobump!(*) = nil
def to_h
raise "cask has no version" if @version.nil?
raise "cask has no URL" if @url.to_s.empty?
{
"token" => @token,
"version" => @version.to_s,
"auto_updates" => @auto_updates,
"url" => @url,
"sha256" => @sha256,
"artifacts" => @artifacts,
"depends_on" => {
"formula" => @formula_dependencies,
"cask" => @cask_dependencies
},
"conflicts_with" => { "cask" => @conflicting_casks },
"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")
}
endView on GitHub (pinned to afd2eddd3a)
Solutions
- Add a `version "..."` stanza to the cask file being evaluated
- Verify the cask file passed via stdin is complete and not truncated
- Check the version stanza uses DSL the shim implements (e.g. plain `version`); unimplemented DSL raises separately or is dropped
- Ensure the correct CASK_FILE/token env is set so the intended cask (not an empty stub) is parsed
Example fix
# before (cask body) cask 'mytool' do url 'https://example.com/mytool.zip' end # after cask 'mytool' do version '1.2.3' url 'https://example.com/mytool-1.2.3.zip' end
Defensive patterns
Strategy: validation
Validate before calling
raise 'cask file missing version stanza' unless File.read(cask_path).match?(/^\s*version\s+/) metadata = eval_cask(cask_path) metadata.to_h
Type guard
valid = m.respond_to?(:to_h) && !m.instance_variable_get(:@version).nil?
Try / catch
begin hash = metadata.to_h rescue RuntimeError => e raise unless e.message == 'cask has no version' # skip/flag cask as incomplete end
Prevention
- Lint cask files for required stanzas (version, url) before running metadata extraction
- Keep cask templates with version pre-filled
- Fail fast on truncated cask files (check file size/content)
When it happens
Trigger: `to_h` is called on a `CaskMetadata` instance whose `@version` is still nil — i.e. the evaluated cask block never called `version ...`, or the DSL stub ignored/failed to record it before `to_h` runs at the end of the eval script.
Common situations: Hand-written or truncated cask files missing the `version` stanza; a cask DSL token the metadata shim doesn't implement causing the version line to be swallowed; copy-pasting a template cask without filling in version; upstream renamed/obsoleted the version stanza style.
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
- cask has no URL
- no cask block found
- #{context}: malformed sha256
- unsupported cask metadata DSL `#{name}`
- remote rustc action metadata is invalid
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/80d228191db4dcac.
Report an issue: GitHub.