d12frosted/homebrew-emacs-plus · error · ConfigurationError

Invalid build.yml at #{path} Expected a YAML mapping (key: v

Error message

Invalid build.yml at #{path}
Expected a YAML mapping (key: value pairs), but got: #{config.class}
Content: #{config.inspect[0..100]}

Common causes:
  - Missing space after colon (use 'icon: value' not 'icon:value')
  - File contains only a string instead of key-value pairs

What it means

The YAML parsed, but the whole document is not a mapping: validate_config! (Library/BuildConfig.rb:154-163) requires the top-level node to be a Hash of key: value pairs and reports the class it actually got (String, Array, Integer, NilClass, ...). The empty-file case is already short-circuited at line 67 (`return {} if content.strip.empty?`), so the NilClass variant almost always comes from a comments-only file - comments alone do not count as empty content to String#strip.

Source

Thrown at Library/BuildConfig.rb:156

                                (expand-file-name (file-name-directory emutls))))
                             "#{prefix}/lib/gcc/current"
                             "#{prefix}/opt/libgccjit/lib/gcc/current"
                             "#{prefix}/lib")))
            (unless (boundp 'native-comp-driver-options)
              (setq native-comp-driver-options nil))
            (dolist (dir dirs)
              (when dir
                (let ((flag (concat "-L" dir)))
                  (unless (member flag native-comp-driver-options)
                    (setq native-comp-driver-options
                          (append native-comp-driver-options (list flag)))))))))
      ELISP
    end

    # 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

View on GitHub (pinned to 01c47fe98f)

Solutions

  1. Make every top-level line a `key: value` pair with a space after the colon - start with `icon: Spacemacs` and re-run.
  2. If you commented out all keys, empty the file completely (zero bytes) or delete it - a comments-only file still reaches the parser and yields nil.
  3. Remove top-level `- item` list syntax; keys may not live under list items.
  4. Verify locally: `ruby -ryaml -e 'p YAML.safe_load(File.read(ARGV[0]))' <file>` must print a Hash (nil is acceptable only for a truly empty file).

Example fix

# before - no space after colon; whole file parses to the String "icon:Spacemacs"
icon:Spacemacs

# after
icon: Spacemacs
Defensive patterns

Strategy: validation

Validate before calling

require "yaml"
content = File.read(path)
parsed = content.strip.empty? ? {} : YAML.safe_load(content, permitted_classes: [Symbol])
abort "#{path}: top level must be a key: value mapping, got #{parsed.class}" unless parsed.is_a?(Hash)

Type guard

def build_yaml_mapping?(path)
  content = File.read(path)
  return true if content.strip.empty?
  YAML.safe_load(content, permitted_classes: [Symbol]).is_a?(Hash)
end

Try / catch

begin
  BuildConfig.load_config
rescue BuildConfig::ConfigurationError => e
  abort e.message if e.message.include?("Expected a YAML mapping")
  raise
end

Prevention

When it happens

Trigger: A build.yml whose top-level parses to anything other than a Hash: the classic `icon:value` with no space after the colon (the whole line becomes one scalar String), a file containing only a bare scalar, a top-level list (`- icon: X`), a lone number/boolean, or a file holding only comments (safe_load returns nil, so the message says NilClass).

Common situations: Forgetting the space after the colon (YAML treats `icon:value` as a scalar string, not a pair); pasting a prose description or chat answer instead of actual config; commenting out every key while debugging and leaving a comments-only file; wrapping config in a top-level list because a website snippet was formatted that way.

Related errors


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