{"record":{"id":"7225349877f12fdd","repo":"github/spec-kit","slug":"could-not-read-manifest-path-e","errorCode":null,"errorMessage":"Could not read manifest {path}: {e}","messagePattern":"Could not read manifest (.+?): (.+?)","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/extensions/__init__.py","lineNumber":255,"sourceCode":"        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}\")\n\n        # Validate schema version\n        if self.data[\"schema_version\"] != self.SCHEMA_VERSION:\n            raise ValidationError(\n                f\"Unsupported schema version: {self.data['schema_version']} \"\n                f\"(expected {self.SCHEMA_VERSION})\"","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/extensions/__init__.py#L237-L273","documentation":"Catch-all for OS-level read failures of the extension manifest other than missing-file and decode errors: the open/read raised OSError (e.g. permission denied, I/O error). The underlying errno message is embedded in the ValidationError.","triggerScenarios":"The manifest exists and decodes but the process cannot read it — EACCES on restrictive file modes, a directory instead of a file (IsADirectoryError is an OSError), or a failing disk/NFS mount.","commonSituations":"Manifest chmod 600 owned by another user; files extracted from an archive that lost permissions; running the CLI as a different user or inside a container with mismatched uid; the manifest path is actually a directory.","solutions":["Read the embedded errno text — 'Permission denied' means fix modes/ownership (`chmod 644`, `chown`); 'Is a directory' means the path is wrong.","Ensure the user running specify has read access to every component of the path.","In containers, check volume mount permissions and uid mapping."],"exampleFix":"# before\n$ ls -l .specify/extensions/my-ext/extension.yaml\n-rw------- 1 root root ... extension.yaml\n\n# after\n$ chmod 644 .specify/extensions/my-ext/extension.yaml","handlingStrategy":"try-catch","validationCode":"import os\nif not os.access(manifest_path, os.R_OK):\n    raise SystemExit(f\"no read permission for {manifest_path}\")","typeGuard":null,"tryCatchPattern":"except ValidationError as e:\n    if \"Could not read manifest\" in str(e):\n        diagnose_errno(e)  # Permission denied -> chmod/chown; Is a directory -> wrong path","preventionTips":["Keep manifests mode 644 owned by the invoking user.","In containers, align uid/gid between host and container for mounted extension dirs."],"tags":["filesystem","permissions","manifest","extensions"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}