github/spec-kit · error · IntegrationDescriptorError

Integration must provide at least one command or script

Error message

Integration must provide at least one command or script

What it means

Raised by IntegrationDescriptor._validate() (src/specify_cli/integrations/catalog.py:781) when 'provides' contains neither commands nor scripts (both default to empty lists). Every integration descriptor must declare at least one artifact so the catalog can guarantee an integration actually installs something.

Source

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

                    )

        provides = self.data["provides"]
        if not isinstance(provides, dict):
            raise IntegrationDescriptorError(
                "'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():

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Add at least one entry to provides.commands (a mapping with 'name' and 'file') or provides.scripts (a relative path string).
  2. If the integration genuinely provides nothing, reconsider whether it should be an integration descriptor at all.
  3. Reload the descriptor to verify validation passes.

Example fix

# before
provides: {}

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

Strategy: validation

Validate before calling

import yaml

def has_provision(data):
    provides = data.get("provides") or {}
    commands = provides.get("commands") or []
    scripts = provides.get("scripts") or []
    return bool(commands) or bool(scripts)

assert has_provision(yaml.safe_load(open("integration.yml")))

Type guard

def provides_something(provides: dict) -> bool:
    return bool(provides.get("commands")) or bool(provides.get("scripts"))

Prevention

When it happens

Trigger: IntegrationDescriptor(path) on a descriptor where 'provides:' is an empty mapping, or where commands/scripts keys are present but set to empty lists — e.g. 'provides: {}' or 'provides: {commands: [], scripts: []}'.

Common situations: Starting a descriptor from a template and not yet filling in the provides section; accidentally commenting out the command list; trimming a descriptor down for testing and removing all entries.

Related errors


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