{"record":{"id":"f0bd2c65b03aec00","repo":"github/spec-kit","slug":"manifest-must-be-a-yaml-mapping-got-type-data","errorCode":null,"errorMessage":"Manifest must be a YAML mapping, got {type(data).__name__}: {path}","messagePattern":"Manifest must be a YAML mapping, got (.+?): (.+?)","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/extensions/__init__.py","lineNumber":257,"sourceCode":"        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})\"\n            )\n","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/extensions/__init__.py#L239-L275","documentation":"Raised after a successful YAML parse when the document root is not a mapping: yaml.safe_load returned a list, string, number, or None (empty file), but an extension manifest must be a mapping of top-level fields. The actual YAML type name is included in the message.","triggerScenarios":"Manifest is an empty file (safe_load → None → 'NoneType'), a YAML list at the root, or a bare scalar document; the isinstance(data, dict) check after loading fails.","commonSituations":"Empty manifest created as a placeholder; a `- item` list pasted at the top level; a fragment that is just a quoted string; truncation during a bad write leaving a partial non-mapping document.","solutions":["Make the document root a mapping with the required top-level keys (schema_version, extension, ...).","If the file is intentionally empty, that is not valid — populate it or remove the extension.","Check the reported type name: 'NoneType' means empty file, 'list' means top-level dash items that must be re-indented under a key."],"exampleFix":"# before\n- schema_version: 2\n- extension:\n    id: my-ext\n\n# after\nschema_version: 2\nextension:\n  id: my-ext","handlingStrategy":"type-guard","validationCode":"data = yaml.safe_load(open(manifest_path, encoding=\"utf-8\"))\nif not isinstance(data, dict):\n    raise SystemExit(\"manifest root must be a YAML mapping\")","typeGuard":"def manifest_is_mapping(data) -> bool:\n    return isinstance(data, dict)","tryCatchPattern":"except ValidationError as e:\n    if \"must be a YAML mapping\" in str(e):\n        restructure_document_root(path)","preventionTips":["Never leave manifest files empty; top level must be key: value pairs.","Beware truncated writes after crashes — re-generate the manifest if it looks cut off."],"tags":["yaml","manifest","extensions","validation"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}