{"record":{"id":"80d228191db4dcac","repo":"jdx/mise","slug":"cask-has-no-version","errorCode":null,"errorMessage":"cask has no version","messagePattern":"cask has no version","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/tap_cask_metadata.rb","lineNumber":250,"sourceCode":"    when :or_older then host <= target || host.same_release?(target)\n    when :or_newer then host >= target\n    else host.same_release?(target)\n    end\n  end\n  private :macos_condition_matches?\n\n  def name(*) = nil\n  def desc(*) = nil\n  def homepage(*) = nil\n  def livecheck(*) = nil\n  def caveats(*) = nil\n  def container(*) = nil\n  def deprecate!(**) = nil\n  def disable!(**) = nil\n  def no_autobump!(*) = nil\n\n  def to_h\n    raise \"cask has no version\" if @version.nil?\n    raise \"cask has no URL\" if @url.to_s.empty?\n    {\n      \"token\" => @token,\n      \"version\" => @version.to_s,\n      \"auto_updates\" => @auto_updates,\n      \"url\" => @url,\n      \"sha256\" => @sha256,\n      \"artifacts\" => @artifacts,\n      \"depends_on\" => {\n        \"formula\" => @formula_dependencies,\n        \"cask\" => @cask_dependencies\n      },\n      \"conflicts_with\" => { \"cask\" => @conflicting_casks },\n      \"ruby_source_path\" => ENV.fetch(\"MISE_BREW_SOURCE_PATH\"),\n      \"ruby_source_checksum\" => { \"sha256\" => ENV.fetch(\"MISE_BREW_SOURCE_CHECKSUM\") },\n      \"tap_git_head\" => ENV.fetch(\"MISE_BREW_TAP_COMMIT\")\n    }\n  end","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/tap_cask_metadata.rb#L232-L268","documentation":"`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.","triggerScenarios":"`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.","commonSituations":"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.","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"],"exampleFix":"# before (cask body)\ncask 'mytool' do\n  url 'https://example.com/mytool.zip'\nend\n# after\ncask 'mytool' do\n  version '1.2.3'\n  url 'https://example.com/mytool-1.2.3.zip'\nend","handlingStrategy":"validation","validationCode":"raise 'cask file missing version stanza' unless File.read(cask_path).match?(/^\\s*version\\s+/)\nmetadata = eval_cask(cask_path)\nmetadata.to_h","typeGuard":"valid = m.respond_to?(:to_h) && !m.instance_variable_get(:@version).nil?\n","tryCatchPattern":"begin\n  hash = metadata.to_h\nrescue RuntimeError => e\n  raise unless e.message == 'cask has no version'\n  # skip/flag cask as incomplete\nend","preventionTips":["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)"],"tags":["ruby","homebrew-cask","metadata","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}