{"record":{"id":"056152025bb40c51","repo":"github/spec-kit","slug":"missing-required-field-field","errorCode":null,"errorMessage":"Missing required field: {field}","messagePattern":"Missing required field: (.+?)","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/extensions/__init__.py","lineNumber":267,"sourceCode":"            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\n        # The REQUIRED_FIELDS loop above only checks key PRESENCE, so a section\n        # that is written but left empty (``provides:`` -> None) or given the\n        # wrong shape (``provides: []``) passes it and then fails on first use:\n        # ``field not in None`` raises TypeError and ``None.get(...)`` raises\n        # AttributeError. Neither is a ValidationError, so both escape the\n        # callers that already handle malformed manifests -- list_installed()'s\n        # \"Corrupted extension\" fallback catches ValidationError only, so one bad\n        # extension made ``specify extension list`` exit 1 with a raw\n        # AttributeError instead of listing the rest. Guard each required\n        # section's shape, mirroring the nested guards below (\"Invalid","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/extensions/__init__.py#L249-L285","documentation":"First structural check in _validate(): each of the manifest's REQUIRED_FIELDS (schema_version, extension, and the other declared required top-level keys) must be present as a key. This checks presence only — shape and type are validated by subsequent checks. Note the companion comment: presence alone is not enough, empty/wrong-shape sections are caught by later guards.","triggerScenarios":"Manifest mapping is missing a required top-level key, e.g. no `schema_version:` or no `extension:` block; validation raises naming the exact missing field.","commonSituations":"Draft manifests written from memory omitting a field; renaming a key (e.g. `metadata:` instead of `extension:`); fields commented out during debugging and forgotten; schema evolution between Specify versions changing the required set.","solutions":["Add the named key at the top level of the manifest.","Compare against a known-good extension manifest or the bundled extension template.","Re-run specify extension install to re-validate."],"exampleFix":"# before\nextension:\n  id: my-ext\n\n# after\nschema_version: 2\nextension:\n  id: my-ext","handlingStrategy":"validation","validationCode":"REQUIRED = {\"schema_version\", \"extension\"}  # mirror ExtensionManifest.REQUIRED_FIELDS\nmissing = REQUIRED - set(data)\nif missing:\n    raise SystemExit(f\"manifest missing required fields: {sorted(missing)}\")","typeGuard":null,"tryCatchPattern":"except ValidationError as e:\n    if str(e).startswith(\"Missing required field\"):\n        add_named_field_and_revalidate(path)","preventionTips":["Start from the official extension template so required fields are always present.","Diff against a working extension's manifest when validation fails."],"tags":["manifest","validation","extensions","required-fields"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}