d12frosted/homebrew-emacs-plus · error · ConfigurationError

Invalid '#{key}' version map in #{path} Version keys must be

Error message

Invalid '#{key}' version map in #{path}
Version keys must be major Emacs versions (e.g. "30") or 'default'.
Got key(s): #{bad.map(&:inspect).join(', ')}

What it means

A version map (used for `icon`, named `patches` entries, and `revision`) contains keys that are neither 'default' nor digit-only strings - i.e. not major Emacs versions. validate_version_map_keys! (Library/BuildConfig.rb:251-259) stringifies each key (`k.to_s`), so unquoted integer keys like `30:` pass and quoted "30" passes, but `"30.1"`, `"29.4"`, word keys (`mac:`), or YAML booleans (`true:` becomes TrueClass, to_s 'true') all fail and are listed with inspect in the message.

Source

Thrown at Library/BuildConfig.rb:255

          raise ConfigurationError,
            "Invalid '#{key}' configuration in #{path}\n" \
            "When specifying an external icon, both 'url' and 'sha256' are required.\n" \
            "Got: #{icon.inspect}"
        end
      else
        raise ConfigurationError,
          "Invalid '#{key}' in #{path}\n" \
          "Expected: string (icon name) or object with 'url' and 'sha256'\n" \
          "Got: #{icon.inspect} (#{icon.class})"
      end
    end

    # Validate that all keys of a version map are major versions or "default"
    def validate_version_map_keys!(map, key, path)
      bad = map.keys.reject { |k| k.to_s == "default" || k.to_s.match?(VERSION_KEY) }
      return if bad.empty?

      raise ConfigurationError,
        "Invalid '#{key}' version map in #{path}\n" \
        "Version keys must be major Emacs versions (e.g. \"30\") or 'default'.\n" \
        "Got key(s): #{bad.map(&:inspect).join(', ')}"
    end

    def validate_inject_path!(value, path)
      return if [true, false].include?(value)

      raise ConfigurationError,
        "Invalid 'inject_path' in #{path}\n" \
        "Expected: true or false\n" \
        "Got: #{value.inspect} (#{value.class})"
    end

    def validate_patches!(patches, path)
      unless patches.is_a?(Array)
        raise ConfigurationError,
          "Invalid 'patches' in #{path}\n" \

View on GitHub (pinned to 01c47fe98f)

Solutions

  1. Use major versions only: "29" instead of "29.4", "30" instead of "30.1" - the build selects the entry by the major version of the Emacs being installed.
  2. Use `default:` as the fallback bucket for everything you do not pin explicitly.
  3. Rename word keys (branch/channel names) to a major version or to default.
  4. If you need an exact point release, put the precise git commit hash under the major bucket - for `revision:` the value is a hex hash validated by validate_revision! anyway.

Example fix

# before - minor version as key
revision:
  "29.4": a1b2c3d4e5f6a7b8

# after - major version key
revision:
  "29": a1b2c3d4e5f6a7b8
Defensive patterns

Strategy: validation

Validate before calling

def version_keys_ok?(map)
  map.keys.all? { |k| k.to_s == "default" || k.to_s.match?(/\A\d+\z/) }
end

%w[icon revision].each do |key|
  v = config_hash[key]
  next unless v.is_a?(Hash) && !(v.keys.map(&:to_s) - %w[url sha256]).empty?
  abort "#{key}: keys must be major Emacs versions or 'default'" unless version_keys_ok?(v)
end

Type guard

def version_map_keys_valid?(map)
  map.keys.all? { |k| k.to_s == "default" || k.to_s.match?(/\A\d+\z/) }
end

Try / catch

begin
  BuildConfig.load_config
rescue BuildConfig::ConfigurationError => e
  if e.message.include?("Version keys must be major Emacs versions")
    abort "Change keys to major versions (\"30\") or 'default' - offending keys are listed in the error"
  end
  raise
end

Prevention

When it happens

Trigger: `revision:` with minor-version keys (`"29.4":`); `icon:` with a word key (`mac:`, `dev:`); YAML 1.1 boolean keys (`on:`, `yes:`, `true:`); or a named patches entry carrying a version map keyed by a minor version like `"29.2"`.

Common situations: Pinning to an exact minor release (29.4, 30.1) without realizing version maps key on MAJOR Emacs versions only; using branch or channel names as keys; unquoted `on:`/`no:` keys silently becoming booleans; following examples written before the version-map feature settled.

Related errors


AI-assisted analysis of d12frosted/homebrew-emacs-plus@01c47fe98f (2026-08-23). Data as JSON: /api/errors/216ea787dad6bf91. Report an issue: GitHub.