{"record":{"id":"a1e7cd11ceec6020","repo":"jdx/mise","slug":"no-cask-block-found","errorCode":null,"errorMessage":"no cask block found","messagePattern":"no cask block found","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/tap_cask_metadata.rb","lineNumber":292,"sourceCode":"  def respond_to_missing?(*) = true\n\n  private\n\n  def add_artifact(kind, source, target)\n    value = [source.to_s]\n    value << { \"target\" => target.to_s } unless target.nil?\n    @artifacts << { kind => value }\n  end\nend\n\ndef cask(token, &block)\n  $mise_cask_metadata = CaskMetadata.new(token)\n  $mise_cask_metadata.instance_eval(&block)\nend\n\neval(STDIN.read.force_encoding(\"UTF-8\"), TOPLEVEL_BINDING, CASK_FILE, 1)\nmetadata = $mise_cask_metadata\nraise \"no cask block found\" if metadata.nil?\nexpected = ENV.fetch(\"MISE_BREW_TOKEN\")\nraise \"expected cask #{expected}, got #{metadata.token}\" if metadata.token != expected\nputs JSON.generate(metadata.to_h)\n","sourceCodeStart":274,"sourceCodeEnd":296,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/tap_cask_metadata.rb#L274-L296","documentation":"At the bottom of the tap cask metadata eval script, the parsed cask metadata is held in `$mise_cask_metadata`, which is only assigned when a `cask ... do ... end` block actually executes. If the evaluated cask file contained no such block (so the global stays nil), the script raises 'no cask block found' before serializing JSON. It's a sanity gate ensuring a cask was actually parsed.","triggerScenarios":"The file piped to STDIN and eval'd contains no top-level `cask '<token>' do ... end` block — e.g. it's a formula (.rb formula), an unrelated Ruby file, an empty/truncated file, or the cask DSL itself failed earlier in a way that skipped the block.","commonSituations":"Pointing the tap metadata extraction at a formula instead of a cask; wrong file path/env var so an empty file is read; cask file that wraps everything in conditionals the top-level binding doesn't execute; tap layout changes moving casks to new paths.","solutions":["Ensure the file evaluated is a cask and begins with a top-level `cask ... do` block","Verify the path/env (CASK_FILE / MISE_BREW_TOKEN) selects the intended cask file in the tap","Re-fetch the tap if the cask file is empty or truncated","Check the cask block isn't guarded by a conditional that prevents it from executing at top level"],"exampleFix":"# before (evaluated file)\n# empty or formula content\n# after\ncask 'mytool' do\n  version '1.2.3'\n  url 'https://example.com/mytool-1.2.3.zip'\n  sha256 :no_check\nend","handlingStrategy":"validation","validationCode":"src = File.read(cask_path)\nraise 'not a cask file' unless src.match?(/^\\s*cask\\s+['\\\"]/)","typeGuard":null,"tryCatchPattern":"begin\n  run_cask_metadata_extraction(cask_path)\nrescue RuntimeError => e\n  raise unless e.message == 'no cask block found'\n  # verify the path points at a cask, not a formula or empty file\nend","preventionTips":["Assert the target file matches /^cask / before extraction","Double-check tap paths and env vars (MISE_BREW_TOKEN, CASK_FILE)","Handle tap layout changes that relocate cask files","Treat empty or suspiciously small cask files as errors early"],"tags":["ruby","homebrew-cask","metadata","missing-block"],"backgroundTag":"entity-not-found","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"}