d12frosted/homebrew-emacs-plus · error · ConfigurationError

Unknown configuration key(s) in #{path}: #{unknown_keys.join

Error message

Unknown configuration key(s) in #{path}: #{unknown_keys.join(', ')}
Valid keys are: #{ALL_KEYS.join(', ')}#{suggestion_text}

What it means

The top-level mapping contains keys outside ALL_KEYS - exactly `icon`, `patches`, `revision`, `inject_path` (the union of FORMULA_KEYS and CASK_KEYS, Library/BuildConfig.rb:15-17). validate_config! computes `config.keys - ALL_KEYS` (line 166) and aborts listing every unknown key, the valid set, and a 'Did you mean' line generated by suggest_key (first-letter match or Levenshtein distance <= 2, lines 184-190). Unknown keys are rejected rather than silently ignored - this tap treats ignored config as a defect.

Source

Thrown at Library/BuildConfig.rb:171

    # Validate that config has the expected structure
    def validate_config!(config, path)
      unless config.is_a?(Hash)
        raise ConfigurationError,
          "Invalid build.yml at #{path}\n" \
          "Expected a YAML mapping (key: value pairs), but got: #{config.class}\n" \
          "Content: #{config.inspect[0..100]}\n\n" \
          "Common causes:\n" \
          "  - Missing space after colon (use 'icon: value' not 'icon:value')\n" \
          "  - File contains only a string instead of key-value pairs"
      end

      # Check for unknown keys
      unknown_keys = config.keys - ALL_KEYS
      unless unknown_keys.empty?
        suggestions = unknown_keys.map { |k| suggest_key(k) }.compact
        suggestion_text = suggestions.empty? ? "" : "\n\nDid you mean:\n#{suggestions.map { |s| "  - #{s}" }.join("\n")}"

        raise ConfigurationError,
          "Unknown configuration key(s) in #{path}: #{unknown_keys.join(', ')}\n" \
          "Valid keys are: #{ALL_KEYS.join(', ')}#{suggestion_text}"
      end

      # Validate individual keys
      validate_icon!(config["icon"], path) if config.key?("icon")
      validate_patches!(config["patches"], path) if config.key?("patches")
      validate_revision!(config["revision"], path) if config.key?("revision")
      validate_inject_path!(config["inject_path"], path) if config.key?("inject_path")
    end

    # Suggest correct key name for typos
    def suggest_key(unknown_key)
      ALL_KEYS.find do |valid_key|
        # Simple similarity: same first letter or Levenshtein distance <= 2
        unknown_key[0]&.downcase == valid_key[0] ||
          levenshtein_distance(unknown_key.downcase, valid_key) <= 2
      end&.then { |key| "'#{unknown_key}' -> '#{key}'" }

View on GitHub (pinned to 01c47fe98f)

Solutions

  1. Rename the unknown key(s) to a valid one - icon, patches, revision, or inject_path - as listed in the message itself.
  2. Check the 'Did you mean' line first: for typos within edit distance 2 (e.g. `icons` -> `icon`) it gives the exact correction.
  3. Delete keys this tap never supported; they had no effect anyway.
  4. Run `brew update && brew info emacs-plus` to confirm the current key names for your tap version, then re-edit the file.

Example fix

# before
icons: Spacemacs

# after
icon: Spacemacs
Defensive patterns

Strategy: validation

Validate before calling

VALID_KEYS = %w[icon patches revision inject_path].freeze
unknown = config_hash.keys.map(&:to_s) - VALID_KEYS
abort "Unknown build.yml key(s): #{unknown.join(', ')}; valid: #{VALID_KEYS.join(', ')}" unless unknown.empty?

Type guard

def known_build_keys?(config)
  (config.keys - %w[icon patches revision inject_path]).empty?
end

Try / catch

begin
  BuildConfig.load_config
rescue BuildConfig::ConfigurationError => e
  abort "Fix these keys, then retry: #{e.message}" if e.message.start_with?("Unknown configuration key")
  raise
end

Prevention

When it happens

Trigger: Any top-level key not in {icon, patches, revision, inject_path}: typos like `icons:`, `icno:`, `patch:`; Ruby-style symbol keys (`:icon: X` parses to a Symbol and does not match the String set); stale keys from older tap releases; or settings from other tools (`env:`, `options:`, `flags:`). Only top-level keys are checked here - shapes nested inside `icon:` are checked by the icon validators.

Common situations: Key renames across emacs-plus releases (a config that worked before `brew update` fails after); users translating old `--with-*` brew command-line flags into build.yml and inventing key names; copying config from a different Emacs distribution's docs; plain hand-editing typos.

Related errors


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