jdx/mise · error · ShimUnsupportedError

cask uses `#{feature}`, which mise's cask shim does not supp

Error message

cask uses `#{feature}`, which mise's cask shim does not support

What it means

mise can install Homebrew casks without Homebrew by evaluating the cask's .rb DSL in its own Ruby shim (cask_shim.rb). The shim deliberately implements only a small surface of the Cask DSL and 'fails loudly instead of falling back to brew' (file header). When a cask's lifecycle code (preflight/postflight hooks) touches something outside that surface, `shim_unsupported!` raises ShimUnsupportedError and the top-level rescue converts it to `odie` — printing `Error: cask uses \`X\`, which mise's cask shim does not support` to stderr and exiting 1. Concrete raisers in the file: `method_missing` on the cask context (any unknown stanza, e.g. `installer`, `depends_on_macos`-style syntax not in the no-op list at cask_shim.rb:274-295), `on_system_conditional` without a branch for the current OS (line 271), `system_command` with unsupported keyword args (line 324), and `on_<macos_version>` with an unknown comparator (line 392).

Source

Thrown at src/system/packages/brew/cask_shim.rb:51

end

MISE_BREW_CASK_FILE = Pathname.new(ENV.fetch("MISE_BREW_CASK_FILE"))
MISE_BREW_CASK_TOKEN = ENV.fetch("MISE_BREW_CASK_TOKEN")
MISE_BREW_CASK_VERSION = ENV.fetch("MISE_BREW_CASK_VERSION")
MISE_BREW_CASK_STAGED_PATH = Pathname.new(ENV.fetch("MISE_BREW_CASK_STAGED_PATH"))
MISE_BREW_CASK_APPDIR = Pathname.new(ENV.fetch("MISE_BREW_CASK_APPDIR"))
MISE_BREW_PREFIX = Pathname.new(ENV.fetch("MISE_BREW_PREFIX"))
MISE_BREW_CASK_HOOK = ENV.fetch("MISE_BREW_CASK_HOOK")

def odie(message)
  $stderr.puts "Error: #{message}"
  exit 1
end

class ShimUnsupportedError < StandardError; end

def shim_unsupported!(feature)
  raise ShimUnsupportedError,
        "cask uses `#{feature}`, which mise's cask shim does not support"
end

module OS
  def self.mac?
    RbConfig::CONFIG["host_os"].include?("darwin")
  end

  def self.linux?
    RbConfig::CONFIG["host_os"].include?("linux")
  end
end

class MacOSVersion
  include Comparable

  SYMBOLS = {
    tahoe: "26", sequoia: "15", sonoma: "14", ventura: "13",

View on GitHub (pinned to 6bd4a54fad)

Solutions

  1. Update mise to the latest release — the shim's supported DSL surface grows over time, and the failing stanza may have been added
  2. Install that cask with real Homebrew instead: `brew install --cask <token>` (mise's shim intentionally does not fall back, so do it explicitly)
  3. Pin the cask to an older version whose hooks only use supported stanzas (e.g. `mise use brew:cask/<token>@<older-version>`) if one is known to work
  4. Check the cask source (brew info --cask <token> or github.com/Homebrew/homebrew-cask) to confirm which stanza triggered it, and file an issue at github.com/jdx/mise with the cask token so the DSL can be added

Example fix

# before (shim fails on unsupported cask stanza)
mise use brew:cask/some-app
# after (use real Homebrew for this cask)
brew install --cask some-app
Defensive patterns

Strategy: fallback

Validate before calling

# probe the cask's hook surface before letting mise install it
# (cask .rb files are plain ruby; check for stanzas outside the shim's no-op list)
ruby -e '
  src = File.read(ARGV[0])
  known = %w[sha256 url name desc homepage livecheck auto_updates conflicts_with depends_on caveats
             app binary pkg font manpage bash_completion zsh_completion fish_completion uninstall zap
             preflight postflight uninstall_preflight uninstall_postflight version arch language
             on_catalina on_big_sur on_monterey on_ventura on_sonoma on_sequoia on_tahoe
             on_intel on_arm on_macos on_linux system_command]
  src.scan(/^\s{2}(\w+)/).flatten.uniq.each { |m| abort "unsupported stanza: #{m}" unless known.include?(m) }
' "$(brew --repository 2>/dev/null)/Caskroom/$(... )" 2>/dev/null || echo "skip probe: check cask manually"

Type guard

# ruby: narrow to the stanzas the cask shim actually implements before running hooks
CASK_SHIM_STANZAS = %w[sha256 url name desc homepage livecheck auto_updates conflicts_with
  depends_on caveats app binary pkg font manpage bash_completion zsh_completion
  fish_completion uninstall zap preflight postflight uninstall_preflight
  uninstall_postflight version arch language staged_path appdir caskroom_path
  system_command on_catalina on_big_sur on_monterey on_ventura on_sonoma
  on_sequoia on_tahoe on_intel on_arm on_macos on_linux].freeze
def shim_compatible_cask?(cask_src)
  calls = cask_src.scan(/^\s{2}(\w+)/).flatten.uniq
  (calls - CASK_SHIM_STANZAS).empty?
end

Try / catch

# shell: detect the shim error and fall back to real Homebrew for this cask
out=$(mise use "brew:cask:$TOKEN" 2>&1)
if [ $? -ne 0 ] && printf '%s' "$out" | grep -q 'cask shim does not support'; then
  brew install --cask "$TOKEN"
else
  printf '%s\n' "$out"
fi

Prevention

When it happens

Trigger: Installing or upgrading a brew cask through mise's system-packages integration (e.g. `mise use brew:cask/<token>` / `mise x brew:cask/<token>`) where the cask's preflight/postflight hook calls an unimplemented stanza, an `on_system_conditional` that only defines `macos:` while you run Linux (or vice versa), or `system_command` with extra kwargs. The error surfaces at hook-evaluation time, after the cask file is fetched and sha-verified but around artifact staging/linking.

Common situations: A cask you installed fine last month breaks after Homebrew updates it to use a newly-added DSL stanza (new macOS release symbols like `on_tahoe` variants, new `installer` forms); running a macos-only cask on Linux; exotic casks with `pkg` installers, license scripts, or `depends_on` blocks that need real brew behavior; mise's shim lagging behind Homebrew DSL evolution.

Related errors


AI-assisted analysis of jdx/mise@6bd4a54fad (2026-08-16). Data as JSON: /api/errors/4fe068c1bae2bdb7. Report an issue: GitHub.