github/spec-kit · error · IntegrationDescriptorError

Invalid provides.scripts: expected a list

Error message

Invalid provides.scripts: expected a list

What it means

Raised by IntegrationDescriptor._validate() (src/specify_cli/integrations/catalog.py:777) when an integration.yml 'provides' mapping declares 'scripts' with a non-list value. The validator treats provides.scripts as an optional list of relative script path strings; a present-but-wrong-typed value aborts descriptor loading with IntegrationDescriptorError.

Source

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

                tool_name = tool.get("name")
                if not isinstance(tool_name, str) or not tool_name.strip():
                    raise IntegrationDescriptorError(
                        "requires.tools entry 'name' must be a non-empty string"
                    )

        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():

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Change provides.scripts in the offending integration.yml to a YAML list of strings.
  2. If no scripts are provided, delete the 'scripts' key so the default empty list is used.
  3. Validate the file again with the catalog loader or the relevant specify command.

Example fix

# before
provides:
  scripts: scripts/bash/setup.sh

# after
provides:
  scripts:
    - scripts/bash/setup.sh
Defensive patterns

Strategy: validation

Validate before calling

import yaml

def validate_provides_scripts(path):
    data = yaml.safe_load(path.read_text()) or {}
    provides = data.get("provides", {})
    if "scripts" in provides and not isinstance(provides["scripts"], list):
        raise ValueError("provides.scripts must be a list of strings")
    return provides.get("scripts", [])

Type guard

def is_valid_scripts_list(scripts) -> bool:
    return isinstance(scripts, list) and all(
        isinstance(s, str) and s.strip() for s in scripts
    )

Try / catch

try:
    desc = IntegrationDescriptor(path)
except IntegrationDescriptorError as e:
    if "provides.scripts" in str(e):
        fix_scripts_key(path)  # rewrite as list or remove key
    else:
        raise

Prevention

When it happens

Trigger: Loading a descriptor whose 'provides:' block has 'scripts:' set to a scalar, mapping, or null-adjacent value (e.g. 'scripts: setup.sh' instead of a list), causing IntegrationDescriptor(path) to raise during _validate().

Common situations: Authoring provides.scripts as a single path string because the integration has only one script; merging descriptors from a format where scripts were a map of names to paths; YAML flow-syntax mistakes.

Related errors


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