{"record":{"id":"78b0959131267837","repo":"github/spec-kit","slug":"manifest-not-found-path","errorCode":null,"errorMessage":"Manifest not found: {path}","messagePattern":"Manifest not found: (.+?)","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/extensions/__init__.py","lineNumber":249,"sourceCode":"            manifest_path: Path to extension.yml file\n\n        Raises:\n            ValidationError: If manifest is invalid\n        \"\"\"\n        self.path = manifest_path\n        self.warnings: List[str] = []\n        self.data = self._load_yaml(manifest_path)\n        self._validate()\n\n    def _load_yaml(self, path: Path) -> dict:\n        \"\"\"Load YAML file safely.\"\"\"\n        try:\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                data = yaml.safe_load(f)\n        except yaml.YAMLError as e:\n            raise ValidationError(f\"Invalid YAML in {path}: {e}\")\n        except FileNotFoundError:\n            raise ValidationError(f\"Manifest not found: {path}\")\n        except UnicodeDecodeError as e:\n            raise ValidationError(\n                f\"Manifest is not valid UTF-8: {path} ({e.reason} at byte {e.start})\"\n            )\n        except OSError as e:\n            raise ValidationError(f\"Could not read manifest {path}: {e}\")\n        if not isinstance(data, dict):\n            raise ValidationError(\n                f\"Manifest must be a YAML mapping, got {type(data).__name__}: {path}\"\n            )\n        return data\n\n    def _validate(self):\n        \"\"\"Validate manifest structure and required fields.\"\"\"\n        # Check required top-level fields\n        for field in self.REQUIRED_FIELDS:\n            if field not in self.data:\n                raise ValidationError(f\"Missing required field: {field}\")","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/extensions/__init__.py#L231-L267","documentation":"Raised when the extension manifest file does not exist at the expected path (FileNotFoundError caught during load). The expected path is included in the message. This is a missing-file error, not a content error.","triggerScenarios":"ExtensionManifest is constructed for `<extension-dir>/extension.yaml` (or the manifest path recorded in the installed registry) and open() raises FileNotFoundError — e.g. the extension directory was deleted or renamed after installation, or an install was incomplete.","commonSituations":"Manually deleting an installed extension's folder under .specify/extensions without unregistering it; git clean/checkout removing untracked extension files; a partially failed install; wrong project root (running specify in a directory that never had the extension).","solutions":["Verify the path in the error message exists (`ls` its parent).","If the extension was deleted manually, clean the registration: `specify extension uninstall <key>` (or --force) then reinstall.","If the install was incomplete, re-run `specify extension install <key>`.","Ensure you are running from the correct project root."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if not manifest_path.is_file():\n    raise SystemExit(f\"missing manifest {manifest_path}; reinstall the extension\")","typeGuard":null,"tryCatchPattern":"except ValidationError as e:\n    if \"Manifest not found\" in str(e):\n        specify_ext_uninstall(key, force=True); specify_ext_install(key)","preventionTips":["Uninstall extensions through the CLI, never by rm -rf on their directories.","After git clean or branch switches, re-check .specify/extensions contents."],"tags":["manifest","extensions","file-not-found","install"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}