github/spec-kit · error · ValidationError

Missing extension.{field}

Error message

Missing extension.{field}

What it means

Raised when the `extension` mapping is missing one of the four metadata fields: id, name, version, or description. Presence is checked per-field before the type check, and the message names the exact missing key (e.g. 'Missing extension.version').

Source

Thrown at src/specify_cli/extensions/__init__.py:308

        ext = self.data["extension"]
        if not isinstance(ext, dict):
            raise ValidationError(
                f"Invalid extension: expected a mapping, got {type(ext).__name__}"
            )
        # Check presence AND type: the format/version checks below feed these
        # values straight to ``re.match`` and ``packaging.Version``, both of
        # which raise a bare TypeError on a non-string. YAML makes that an easy
        # authoring slip -- unquoted ``version: 1.0`` parses as a float and
        # ``id: 2`` as an int -- and TypeError is not a ValidationError, so it
        # escapes every caller that already handles a malformed manifest (see
        # list_installed()'s "Corrupted extension" fallback, which catches
        # ValidationError only, making one bad extension exit ``specify
        # extension list`` with a raw traceback and hide the healthy ones).
        # Mirrors the sibling IntegrationDescriptor, which already type-checks
        # the same four fields.
        for field in ["id", "name", "version", "description"]:
            if field not in ext:
                raise ValidationError(f"Missing extension.{field}")
            if not isinstance(ext[field], str):
                raise ValidationError(
                    f"Invalid extension.{field}: expected a string, "
                    f"got {type(ext[field]).__name__}"
                )

        # Validate extension ID format
        if not re.match(r"^[a-z0-9-]+$", ext["id"]):
            raise ValidationError(
                f"Invalid extension ID '{ext['id']}': "
                "must be lowercase alphanumeric with hyphens only"
            )

        # Validate semantic version
        try:
            pkg_version.Version(ext["version"])
        except pkg_version.InvalidVersion:
            raise ValidationError(f"Invalid version: {ext['version']}")

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Add the named field under `extension:`.
  2. Ensure all four — id, name, version, description — are present.
  3. Quote version as a string (`version: "1.0.0"`) to avoid the float-type trap caught by the next check.

Example fix

# before
extension:
  id: my-ext
  name: My Extension
  description: Does things

# after
extension:
  id: my-ext
  name: My Extension
  version: "1.0.0"
  description: Does things
Defensive patterns

Strategy: validation

Validate before calling

EXT_FIELDS = ["id", "name", "version", "description"]
missing = [f for f in EXT_FIELDS if f not in data.get("extension", {})]
if missing:
    raise SystemExit(f"extension section missing: {missing}")

Try / catch

except ValidationError as e:
    if str(e).startswith("Missing extension."):
        add_missing_metadata_field(path)

Prevention

When it happens

Trigger: Manifest's extension block defines id/name/description but omits `version:` (the most commonly forgotten), or any other of the four; the field loop raises on the first absent key.

Common situations: Hand-authored manifests; copying a partial example; deleting a field while editing and forgetting to restore it; assuming description is optional (it is not).

Related errors


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/c4a588a6d2641c00. Report an issue: GitHub.