d12frosted/homebrew-emacs-plus · error · ConfigurationError

Invalid '#{key}' configuration in #{path} When specifying an

Error message

Invalid '#{key}' configuration in #{path}
When specifying an external icon, both 'url' and 'sha256' are required.
Got: #{icon.inspect}

What it means

An icon entry is a Hash but does not carry both a truthy `url` and `sha256` - validate_icon_spec! (Library/BuildConfig.rb:235-241) requires exactly these two keys because the build must download and checksum-verify the file. The '{key}' in the message tells you where: 'icon' for the top-level entry, 'icon.30' inside a version map. By design `icon: {}` (empty hash) also lands here (see the comment at lines 212-213): an empty hash is neither a usable spec nor a usable version map.

Source

Thrown at Library/BuildConfig.rb:237

              "Invalid 'icon.#{ver}' in #{path}\n" \
              "Version maps cannot be nested.\n" \
              "Got: #{spec.inspect}"
          end
          validate_icon_spec!(spec, path, key: "icon.#{ver}")
        end
      else
        validate_icon_spec!(icon, path)
      end
    end

    def validate_icon_spec!(icon, path, key: "icon")
      case icon
      when String, nil
        # Valid: icon name from registry or no icon
        return
      when Hash
        unless icon["url"] && icon["sha256"]
          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,

View on GitHub (pinned to 01c47fe98f)

Solutions

  1. Add the missing key: fetch the file and compute the digest - `curl -LO <url> && shasum -a 256 <file>` - then paste the hex after `sha256:`.
  2. Fix key-name typos - the hash must use exactly `url` and `sha256`, no aliases.
  3. If you wanted a bundled icon instead, replace the whole hash with a plain registry name: `icon: Spacemacs`.
  4. If you wanted no icon at all, delete the `icon:` key entirely - `icon: {}` is not 'no icon' and still raises this error.

Example fix

# before - missing sha256
icon:
  url: https://example.com/Emacs.icns

# after
icon:
  url: https://example.com/Emacs.icns
  sha256: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Defensive patterns

Strategy: validation

Validate before calling

def external_icon_complete?(spec)
  spec.is_a?(Hash) && !!spec["url"] && !!spec["sha256"]
end

icon = config_hash["icon"]
spec_map = icon.is_a?(Hash) && !(icon.keys.map(&:to_s) - %w[url sha256]).empty?
if spec_map
  icon.each { |ver, s| abort "icon.#{ver}: url and sha256 both required" unless external_icon_complete?(s) }
elsif icon.is_a?(Hash)
  abort "icon: url and sha256 both required" unless external_icon_complete?(icon)
end

Type guard

def valid_icon_entry?(v)
  v.is_a?(String) || v.nil? || (v.is_a?(Hash) && !!v["url"] && !!v["sha256"])
end

Try / catch

begin
  BuildConfig.load_config
rescue BuildConfig::ConfigurationError => e
  if e.message.include?("both 'url' and 'sha256' are required")
    abort "Compute the digest with: curl -LO <url> && shasum -a 256 <file>"
  end
  raise
end

Prevention

When it happens

Trigger: `icon:` with a hash containing url but no sha256 (or vice versa); a key present but value empty (`url:` with nothing after it parses to nil, which is falsy); typo'd key names (`sha:`, `checksum:`); `icon: {}`; or a version-map entry like `"30": {url: ...}` missing the digest.

Common situations: Skipping the sha256 because it is tedious to compute, then hitting it at install time; key names copied from another tool's config (sha, sha_sum, checksum); an incompletely pasted block where the last line was dropped; assuming the digest is optional - it never is for external resources.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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