{"record":{"id":"f0a19b267b6b0304","repo":"github/spec-kit","slug":"manifest-is-not-valid-utf-8-path-e-reason-at","errorCode":null,"errorMessage":"Manifest is not valid UTF-8: {path} ({e.reason} at byte {e.start})","messagePattern":"Manifest is not valid UTF-8: (.+?) \\((.+?) at byte (.+?)\\)","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/extensions/__init__.py","lineNumber":251,"sourceCode":"        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}\")\n\n        # Validate schema version","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/extensions/__init__.py#L233-L269","documentation":"Raised when the extension manifest contains bytes that are not valid UTF-8: the file was opened with encoding='utf-8' and Python raised UnicodeDecodeError. The message includes the reason (e.g. 'invalid start byte') and the byte offset where decoding failed.","triggerScenarios":"Manifest was saved in a legacy 8-bit encoding (Latin-1, Windows-1252) or contains binary garbage; open(..., encoding='utf-8') fails at the reported byte offset.","commonSituations":"Editing the manifest in an editor that saved as ANSI/Latin-1 (common on Windows with non-ASCII characters in the description); copy-pasting text with a stray BOM-less non-UTF8 byte; a binary file accidentally placed at the manifest path.","solutions":["Reopen the file at the reported byte offset to find the offending character.","Re-save the manifest as UTF-8 (editors: 'Save with encoding → UTF-8').","Prefer ASCII-only manifest text to avoid encoding drift entirely."],"exampleFix":"# before: description saved as Latin-1 containing 'café'\n# after: re-save file with UTF-8 encoding\ndescription: \"café\"","handlingStrategy":"validation","validationCode":"try:\n    open(manifest_path, encoding=\"utf-8\").read()\nexcept UnicodeDecodeError:\n    raise SystemExit(\"manifest must be UTF-8; re-save with UTF-8 encoding\")","typeGuard":null,"tryCatchPattern":"except ValidationError as e:\n    if \"not valid UTF-8\" in str(e):\n        transcode_to_utf8(path)  # read as detected legacy encoding, rewrite as UTF-8","preventionTips":["Save all manifests as UTF-8; prefer ASCII-only metadata text.","On Windows, set the editor's default file encoding to UTF-8."],"tags":["encoding","utf-8","manifest","extensions"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}