github/spec-kit · error · ValidationError
Hook '{hook_name}' missing required 'command' field
Error message
Hook '{hook_name}' missing required 'command' field What it means
Every hook entry mapping must contain a truthy command field — the executable string the hook dispatcher runs. Missing, empty, or null command values are rejected.
Source
Thrown at src/specify_cli/extensions/__init__.py:425
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"
)
if priority < 1:
raise ValidationError(
f"Hook '{hook_name}' has invalid 'priority': "
"must be >= 1"
)
# Validate commands; track renames so hook references can be rewritten.
rename_map: Dict[str, str] = {}
for cmd in commands:View on GitHub (pinned to bf88c9f9a8)
Solutions
- Add `command: <executable or script path>` to the hook entry.
- Use the exact key name `command` — synonyms like cmd/script/run are not recognized.
- Ensure the value is non-empty; an empty string fails.
Example fix
# before
hooks:
post-install:
- script: ./setup.sh
# after
hooks:
post-install:
- command: ./setup.sh Defensive patterns
Strategy: validation
Validate before calling
def hook_commands_present(data: dict) -> bool:
hooks = data.get("hooks") or {}
for cfg in hooks.values():
entries = cfg if isinstance(cfg, list) else [cfg]
for e in entries:
if not isinstance(e, dict) or not e.get("command"):
return False
return True Prevention
- The key is literally `command` — not cmd, script, or run.
- Fill it with a non-empty executable string before installing.
When it happens
Trigger: A hook entry `{handler: setup}` (no command), `{command: ""}`, or `{command: null}`. entry.get("command") is falsy and the error names the hook.
Common situations: Author names the key `cmd` or `script` instead of `command`, or leaves a placeholder empty while drafting the manifest.
Related errors
- Missing requires.speckit_version
- Invalid hooks: expected a mapping
- Extension must provide at least one command, hook, or event
- Invalid hook '{hook_name}': list must contain at least one e
- Invalid hook '{hook_name}': expected a mapping or list of ma
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/5c7f25a63e53ab29.
Report an issue: GitHub.