{"record":{"id":"c5a1ad118c96c56a","repo":"github/spec-kit","slug":"hook-hook-name-has-invalid-priority-must-be","errorCode":null,"errorMessage":"Hook '{hook_name}' has invalid 'priority': must be an integer","messagePattern":"Hook '(.+?)' has invalid 'priority': must be an integer","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/extensions/__init__.py","lineNumber":431,"sourceCode":"            for hook_name, hook_config in hooks.items():\n                if isinstance(hook_config, list) and not hook_config:\n                    raise ValidationError(\n                        f\"Invalid hook '{hook_name}': list must contain at least one entry\"\n                    )\n                for entry in coerce_hook_entries(hook_config):\n                    if not isinstance(entry, dict):\n                        raise ValidationError(\n                            f\"Invalid hook '{hook_name}': \"\n                            \"expected a mapping or list of mappings\"\n                        )\n                    if not entry.get(\"command\"):\n                        raise ValidationError(\n                            f\"Hook '{hook_name}' missing required 'command' field\"\n                        )\n                    if \"priority\" in entry:\n                        priority = entry[\"priority\"]\n                        if not isinstance(priority, int) or isinstance(priority, bool):\n                            raise ValidationError(\n                                f\"Hook '{hook_name}' has invalid 'priority': \"\n                                \"must be an integer\"\n                            )\n                        if priority < 1:\n                            raise ValidationError(\n                                f\"Hook '{hook_name}' has invalid 'priority': \"\n                                \"must be >= 1\"\n                            )\n\n        # Validate commands; track renames so hook references can be rewritten.\n        rename_map: Dict[str, str] = {}\n        for cmd in commands:\n            if not isinstance(cmd, dict):\n                raise ValidationError(\n                    \"Each command entry in 'provides.commands' must be a mapping\"\n                )\n            if \"name\" not in cmd or \"file\" not in cmd:\n                raise ValidationError(\"Command missing 'name' or 'file'\")","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/extensions/__init__.py#L413-L449","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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."],"exampleFix":"# before\n- command: ./setup.sh\n  priority: high\n\n# after\n- command: ./setup.sh\n  priority: 10","handlingStrategy":"type-guard","validationCode":"def priorities_valid(data: dict) -> bool:\n    hooks = data.get(\"hooks\") or {}\n    for cfg in hooks.values():\n        entries = cfg if isinstance(cfg, list) else [cfg]\n        for e in entries:\n            p = e.get(\"priority\") if isinstance(e, dict) else None\n            if p is not None and (not isinstance(p, int) or isinstance(p, bool)):\n                return False\n    return True","typeGuard":"def is_true_int(v: object) -> bool:\n    return isinstance(v, int) and not isinstance(v, bool)","tryCatchPattern":null,"preventionTips":["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."],"tags":["extension-manifest","validation","hooks","typing"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}