github/spec-kit · error · IntegrationDescriptorError

Each command entry must be a mapping

Error message

Each command entry must be a mapping

What it means

Raised by IntegrationDescriptor._validate() (src/specify_cli/integrations/catalog.py:786) while iterating provides.commands: an element of the commands list is not a YAML mapping. Each command entry must be a dict (later checked for 'name' and 'file' keys), so scalar or nested-list entries are rejected.

Source

Thrown at src/specify_cli/integrations/catalog.py:786

                "'provides' must be a mapping"
            )
        commands = provides.get("commands", [])
        scripts = provides.get("scripts", [])
        if "commands" in provides and not isinstance(commands, list):
            raise IntegrationDescriptorError(
                "Invalid provides.commands: expected a list"
            )
        if "scripts" in provides and not isinstance(scripts, list):
            raise IntegrationDescriptorError(
                "Invalid provides.scripts: expected a list"
            )
        if not commands and not scripts:
            raise IntegrationDescriptorError(
                "Integration must provide at least one command or script"
            )
        for cmd in commands:
            if not isinstance(cmd, dict):
                raise IntegrationDescriptorError(
                    "Each command entry must be a mapping"
                )
            if "name" not in cmd or "file" not in cmd:
                raise IntegrationDescriptorError(
                    "Command entry missing 'name' or 'file'"
                )
            cmd_name = cmd["name"]
            cmd_file = cmd["file"]
            if not isinstance(cmd_name, str) or not cmd_name.strip():
                raise IntegrationDescriptorError(
                    "Command entry 'name' must be a non-empty string"
                )
            if not isinstance(cmd_file, str) or not cmd_file.strip():
                raise IntegrationDescriptorError(
                    "Command entry 'file' must be a non-empty string"
                )
            if os.path.isabs(cmd_file) or ".." in Path(cmd_file).parts or Path(cmd_file).drive or Path(cmd_file).anchor:
                raise IntegrationDescriptorError(

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Wrap every element of provides.commands in a mapping with at least 'name' and 'file' keys.
  2. Check for mixed entries (some dicts, some strings) — all must be mappings.
  3. Re-validate the descriptor.

Example fix

# before
provides:
  commands:
    - plan
    - build

# after
provides:
  commands:
    - name: plan
      file: commands/plan.md
    - name: build
      file: commands/build.md
Defensive patterns

Strategy: validation

Validate before calling

def valid_command_entries(commands):
    return all(isinstance(c, dict) for c in commands)

Type guard

from typing import Any

def is_command_entry(entry: Any) -> bool:
    return isinstance(entry, dict)

Prevention

When it happens

Trigger: A descriptor with 'provides: commands: [plan, build]' or a list of lists; the for-loop over commands hits a non-dict element and raises IntegrationDescriptorError immediately.

Common situations: Writing a shorthand list of command names instead of full mappings; converting a JSON list of strings into YAML without wrapping each in an object; inconsistent entry formats within one list.

Related errors


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/fd768a5003b30a78. Report an issue: GitHub.