github/spec-kit · error · ValidationError
Hook '{hook_name}' has invalid 'priority': must be an intege
Error message
Hook '{hook_name}' has invalid 'priority': must be an integer What it means
The optional priority field on a hook entry must be a true integer. The check explicitly excludes booleans (`isinstance(priority, bool)`), because bool is a subclass of int in Python — `priority: true` would otherwise pass as priority 1.
Source
Thrown at src/specify_cli/extensions/__init__.py:431
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:
if not isinstance(cmd, dict):
raise ValidationError(
"Each command entry in 'provides.commands' must be a mapping"
)
if "name" not in cmd or "file" not in cmd:
raise ValidationError("Command missing 'name' or 'file'")View on GitHub (pinned to bf88c9f9a8)
Solutions
- Use a plain integer: `priority: 10`.
- Remove named-level values; the schema accepts only ints.
- If YAML produced a float (e.g. `priority: 10.0`), write it without the decimal point.
Example fix
# before - command: ./setup.sh priority: high # after - command: ./setup.sh priority: 10
Defensive patterns
Strategy: type-guard
Validate before calling
def priorities_valid(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:
p = e.get("priority") if isinstance(e, dict) else None
if p is not None and (not isinstance(p, int) or isinstance(p, bool)):
return False
return True Type guard
def is_true_int(v: object) -> bool:
return isinstance(v, int) and not isinstance(v, bool) Prevention
- priority accepts plain integers only (>= 1); booleans pass isinstance(int) but are explicitly rejected.
- Quote or avoid values like `true`/`high` that YAML or habit introduce.
When it happens
Trigger: `priority: high`, `priority: 1.5`, or `priority: true` on a hook entry. isinstance(priority, int) is false, or it is true but the value is a bool, so the error fires.
Common situations: Author assumes priority accepts named levels (high/low), or YAML's `true` sneaks in from a boolean flag. Float priorities from YAML (`1.0`) also fail because YAML parses unquoted 1.0 as float.
Related errors
- Invalid hooks: expected a mapping
- Invalid hook '{hook_name}': list must contain at least one e
- Invalid hook '{hook_name}': expected a mapping or list of ma
- Hook '{hook_name}' missing required 'command' field
- Command missing 'name' or 'file'
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/c5a1ad118c96c56a.
Report an issue: GitHub.