{"record":{"id":"b744f4e94152b3ee","repo":"github/spec-kit","slug":"priority-must-be-a-positive-integer-1-or-higher-b744f4","errorCode":null,"errorMessage":"Priority must be a positive integer (1 or higher)","messagePattern":"Priority must be a positive integer \\(1 or higher\\)","errorType":"validation","errorClass":"PresetValidationError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/presets/__init__.py","lineNumber":3558,"sourceCode":"    ) -> PresetManifest:\n        \"\"\"Install preset from a local directory.\n\n        Args:\n            source_dir: Path to preset directory\n            speckit_version: Current spec-kit version\n            priority: Resolution priority (lower = higher precedence, default 10)\n            force: If True and the preset is already installed, remove it first\n\n        Returns:\n            Installed preset manifest\n\n        Raises:\n            PresetValidationError: If manifest is invalid or priority is invalid\n            PresetCompatibilityError: If pack is incompatible\n        \"\"\"\n        # Validate priority\n        if priority < 1:\n            raise PresetValidationError(\"Priority must be a positive integer (1 or higher)\")\n\n        manifest_path = source_dir / \"preset.yml\"\n        manifest = PresetManifest(manifest_path)\n\n        self.check_compatibility(manifest, speckit_version)\n\n        if self.registry.is_installed(manifest.id):\n            if not force:\n                raise PresetError(\n                    f\"Preset '{manifest.id}' is already installed. \"\n                    f\"Use 'specify preset remove {manifest.id}' first.\"\n                )\n            self.remove(manifest.id)\n\n        dest_dir = self.presets_dir / manifest.id\n        if dest_dir.exists():\n            shutil.rmtree(dest_dir)\n","sourceCodeStart":3540,"sourceCodeEnd":3576,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/presets/__init__.py#L3540-L3576","documentation":"PresetManager.install_from_directory validates the resolution priority argument up front: priority must be >= 1 (lower number = higher precedence, default 10). Zero, negative numbers, or any value below 1 raise PresetValidationError before the manifest is even read.","triggerScenarios":"Calling install_from_directory(source_dir, speckit_version, priority=0) or priority=-5 programmatically, or a CLI/automation layer passing an unvalidated user-supplied number.","commonSituations":"Treating priority as 0-indexed (like array ranks), using 0 as a sentinel for \"highest\", or computing priority from an arithmetic expression that can go negative.","solutions":["Pass priority=1 for maximum precedence; 10 is the conventional default.","Clamp user/automation input before calling: `priority = max(1, int(priority))`.","Use None-checks for 'unset' rather than 0."],"exampleFix":"# before\nmanager.install_from_directory(src, ver, priority=0)\n\n# after\nmanager.install_from_directory(src, ver, priority=1)","handlingStrategy":"validation","validationCode":"priority = max(1, int(priority))\nmanager.install_from_directory(source_dir, speckit_version, priority=priority)","typeGuard":"def is_valid_priority(p) -> bool:\n    return isinstance(p, int) and not isinstance(p, bool) and p >= 1","tryCatchPattern":"try:\n    manager.install_from_directory(src, ver, priority=p)\nexcept PresetValidationError as e:\n    if \"Priority\" in str(e):\n        p = 10  # fall back to the conventional default\n        manager.install_from_directory(src, ver, priority=p)","preventionTips":["Priority starts at 1 (highest precedence); default is 10.","Do not use 0 as a 'highest' or 'unset' sentinel.","Clamp external/automation inputs at the boundary: max(1, int(x))."],"tags":["preset","install","priority","validation"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}