jdx/mise · error · RuntimeError

expected cask #{expected}, got #{metadata.token}

Error message

expected cask #{expected}, got #{metadata.token}

What it means

mise's cask metadata extractor evals a Homebrew cask DSL file and compares the token passed to the top-level `cask` block against the expected token supplied via the MISE_BREW_TOKEN environment variable. When the cask file actually defines a different cask token than the one mise requested, this sanity-check raise fires with both tokens in the message. It guards against evaluating the wrong cask file (e.g. a mis-mapped source path or a renamed cask).

Source

Thrown at src/system/packages/brew/tap_cask_metadata.rb:294

  private

  def add_artifact(kind, source, target)
    value = [source.to_s]
    value << { "target" => target.to_s } unless target.nil?
    @artifacts << { kind => value }
  end
end

def cask(token, &block)
  $mise_cask_metadata = CaskMetadata.new(token)
  $mise_cask_metadata.instance_eval(&block)
end

eval(STDIN.read.force_encoding("UTF-8"), TOPLEVEL_BINDING, CASK_FILE, 1)
metadata = $mise_cask_metadata
raise "no cask block found" if metadata.nil?
expected = ENV.fetch("MISE_BREW_TOKEN")
raise "expected cask #{expected}, got #{metadata.token}" if metadata.token != expected
puts JSON.generate(metadata.to_h)

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Compare the two tokens in the message and make MISE_BREW_TOKEN match the token declared in the cask file's `cask "..."` block
  2. Verify MISE_BREW_SOURCE_PATH points at the file for the requested cask (re-check the tap's Cask/ path spelling and case)
  3. If the cask was renamed upstream, update the mise brew registry mapping/tool reference to the new token
  4. Refresh the tap (git pull / re-fetch) so the file content matches the token you requested

Example fix

// before: requesting the wrong token
//   MISE_BREW_TOKEN="google-chrome"
//   cask "googlechrome" do ... end  # actual token in file
// after
//   MISE_BREW_TOKEN="googlechrome"
//   cask "googlechrome" do ... end
Defensive patterns

Strategy: validation

Validate before calling

# Run before invoking the extractor
token = File.read(cask_path)[/\bcask\s+["']([^"']+)["']/, 1]
raise "cask file token #{token.inspect} != expected #{expected.inspect}" if token != expected

Type guard

def cask_token_matches?(file, expected)
  File.read(file)[/^\s*cask\s+["']([^"']+)["']/, 1] == expected
end

Try / catch

begin
  extract_cask_metadata(cask_path, token: expected)
rescue RuntimeError => e
  raise unless e.message.start_with?("expected cask ")
  warn "Requested token differs from cask file token: #{e.message}; re-check tap mapping"
end

Prevention

When it happens

Trigger: Running src/system/packages/brew/tap_cask_metadata.rb with MISE_BREW_SOURCE_PATH pointing at a cask file whose `cask "some-token"` block does not match MISE_BREW_TOKEN — e.g. a casing/underscore mismatch, an alias cask file, or a cask renamed upstream.

Common situations: A third-party tap renamed a cask but the mise registry mapping still references the old token; the wrong file was fetched for the requested token (tap index stale or URL construction bug); casks with hyphens/underscores where token normalization differs; internal token like `cask "foo@x"` vs requested `foo`.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/dda37ddf5a1500db. Report an issue: GitHub.