d12frosted/homebrew-emacs-plus · error · ConfigurationError

Invalid 'icon.#{ver}' in #{path} Version maps cannot be nest

Error message

Invalid 'icon.#{ver}' in #{path}
Version maps cannot be nested.
Got: #{spec.inspect}

What it means

`icon` was recognized as a version map (a Hash that is not a {url, sha256} spec), so validate_icon! iterates its version -> spec entries - and found an entry whose value is itself another map (version_map?(spec) true, Library/BuildConfig.rb:217). Version maps are exactly one level deep: each version key must map straight to a String (registry icon name) or a {url, sha256} spec, never to another map. The message names the offending version key ('icon.30' style) and shows the nested value.

Source

Thrown at Library/BuildConfig.rb:218

        prev = d[0]
        d[0] = j
        (1..m).each do |i|
          temp = d[i]
          d[i] = [d[i] + 1, d[i - 1] + 1, prev + (s1[i - 1] == s2[j - 1] ? 0 : 1)].min
          prev = temp
        end
      end
      d[m]
    end

    def validate_icon!(icon, path)
      # An empty hash is neither a usable spec nor a version map; let the
      # spec validator produce the "url and sha256 required" error for it
      if version_map?(icon) && !icon.empty?
        validate_version_map_keys!(icon, "icon", path)
        icon.each do |ver, spec|
          if version_map?(spec)
            raise ConfigurationError,
              "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"]

View on GitHub (pinned to 01c47fe98f)

Solutions

  1. Flatten the map: every version key sits directly under `icon:`, and each maps straight to a name or a {url, sha256} spec.
  2. Move `default:` to be a sibling of the version keys (a direct child of `icon:`), not nested inside one.
  3. Check indentation - two spaces per level, with all version keys aligned under `icon:`.
  4. If you only need one icon, drop the version map entirely and use `icon: Spacemacs` or the flat {url, sha256} form.

Example fix

# before - 'default' nested inside the "30" entry
icon:
  "30":
    default:
      url: https://example.com/e30.icns
      sha256: 1111111111111111111111111111111111111111111111111111111111111111

# after - one level: version keys map straight to specs
icon:
  default:
    url: https://example.com/generic.icns
    sha256: 2222222222222222222222222222222222222222222222222222222222222222
  "30":
    url: https://example.com/e30.icns
    sha256: 1111111111111111111111111111111111111111111111111111111111111111
Defensive patterns

Strategy: validation

Validate before calling

# Mirror of BuildConfig.version_map?: a hash that is NOT a {url, sha256} spec
def version_map?(v)
  v.is_a?(Hash) && !(v.keys.map(&:to_s) - %w[url sha256]).empty?
end

icon = config_hash["icon"]
if version_map?(icon)
  icon.each do |ver, spec|
    abort "icon.#{ver}: version maps cannot be nested - flatten one level" if version_map?(spec)
  end
end

Type guard

def icon_shape_ok?(icon)
  spec_map = ->(v) { v.is_a?(Hash) && !(v.keys.map(&:to_s) - %w[url sha256]).empty? }
  return true unless spec_map.call(icon)
  icon.values.none? { |v| spec_map.call(v) }
end

Try / catch

begin
  BuildConfig.load_config
rescue BuildConfig::ConfigurationError => e
  if e.message.include?("Version maps cannot be nested")
    abort "Flatten icon: one level of version keys, each mapping to a name or {url, sha256}"
  end
  raise
end

Prevention

When it happens

Trigger: A build.yml shaped like `icon:` / ` "30":` / ` default:` / ` url: ...` - a 'default' (or a second version) nested inside a version key; any indentation slip that pushes a version key one level under another version key; or merging two example configs so specs end up double-wrapped.

Common situations: Users combining a fallback icon with per-version icons and assuming 'default' lives inside each version entry; copy-paste of nested examples from issues or blogs; indentation off by two spaces so a key lands under the wrong parent.

Related errors


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