github/spec-kit · error · ValidationError

Invalid hook ' ': list must contain at least one entry

Error message

Invalid hook '{hook_name}': list must contain at least one entry

What it means

When a hook's value is a list, that list must contain at least one entry. An explicitly empty list (`hook-name: []`) is treated as a declaration with no behavior, which validation rejects rather than silently installing a no-op hook.

Solutions

  1. Delete the hook key entirely if you don't want the hook.
  2. Or populate the list with at least one mapping: `- command: ./script.sh`.
  3. Don't use an empty list as a 'disabled' marker — the schema has no such concept.

Example fix

# before
hooks:
  post-install: []

# after (omit it, or provide an entry)
# hooks:
#   post-install: []
# or
hooks:
  post-install:
    - command: ./setup.sh
Defensive patterns

Strategy: validation

Validate before calling

def hook_lists_nonempty(data: dict) -> bool:
    hooks = data.get("hooks") or {}
    return all(not isinstance(v, list) or len(v) > 0 for v in hooks.values())

Prevention

When it happens

Trigger: `hooks:\n post-install: []` — hook_config is a list and `not hook_config` is true, so the error names the hook.

Common situations: Author disables a hook by emptying its list instead of deleting the key, or a generator template emits empty lists for unconfigured hooks.

Related errors


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

Appendix: source

Thrown at src/specify_cli/extensions/__init__.py:415

        has_events = bool(events)
        has_templates = bool(templates)
        has_scripts = bool(scripts)

        if not has_commands and not has_hooks and not has_events and not has_templates and not has_scripts:
            raise ValidationError(
                "Extension must provide at least one command, hook, or event "
                "(or a declared template/script)"
            )

        self._validate_provided_artifacts(templates, section="templates", singular="template")
        self._validate_provided_artifacts(scripts, section="scripts", singular="script")

        # Validate hook values (if present).
        # Each event is a single mapping or a list of mappings.
        if hooks:
            for hook_name, hook_config in hooks.items():
                if isinstance(hook_config, list) and not hook_config:
                    raise ValidationError(
                        f"Invalid hook '{hook_name}': list must contain at least one entry"
                    )
                for entry in coerce_hook_entries(hook_config):
                    if not isinstance(entry, dict):
                        raise ValidationError(
                            f"Invalid hook '{hook_name}': "
                            "expected a mapping or list of mappings"
                        )
                    if not entry.get("command"):
                        raise ValidationError(
                            f"Hook '{hook_name}' missing required 'command' field"
                        )
                    if "priority" in entry:
                        priority = entry["priority"]
                        if not isinstance(priority, int) or isinstance(priority, bool):
                            raise ValidationError(
                                f"Hook '{hook_name}' has invalid 'priority': "
                                "must be an integer"

View on GitHub (pinned to bf88c9f9a8)