github/spec-kit · error · PresetCompatibilityError

Preset requires spec-kit {required}, but {speckit_version} i

Error message

Preset requires spec-kit {required}, but {speckit_version} is installed.\nUpgrade spec-kit with: {REINSTALL_COMMAND}

What it means

The preset declares a requires.speckit_version range that the currently installed specify-cli does not satisfy, so install aborts before copying any files. The message includes the required range, the installed version, and the canonical reinstall command (`uv tool install specify-cli --force --from git+https://github.com/github/spec-kit.git`).

Source

Thrown at src/specify_cli/presets/__init__.py:818

        # Defense in depth: the manifest validator now rejects a non-string
        # requires.speckit_version, but this method is public and also reachable
        # with a hand-built manifest object. ``InvalidSpecifier`` alone does not
        # cover a non-string -- scalars raise TypeError from the constructor, and
        # a list/dict is iterable so it constructs here and only breaks inside
        # .contains(). Reject up front so this always reports a
        # PresetCompatibilityError.
        if not isinstance(required, str):
            raise PresetCompatibilityError(
                "Invalid version specifier: expected a string, got "
                f"{type(required).__name__} ({required!r})"
            )
        try:
            SpecifierSet(required)  # Just to validate
        except InvalidSpecifier:
            raise PresetCompatibilityError(f"Invalid version specifier: {required}")

        if not version_satisfies(speckit_version, required):
            raise PresetCompatibilityError(
                f"Preset requires spec-kit {required}, "
                f"but {speckit_version} is installed.\n"
                f"Upgrade spec-kit with: {REINSTALL_COMMAND}"
            )

        return True

    def _register_commands(
        self,
        manifest: PresetManifest,
        preset_dir: Path
    ) -> Dict[str, List[str]]:
        """Register preset command overrides with all detected AI agents.

        Scans the preset's templates for type "command", reads each command
        file, and writes it to every detected agent directory using the
        CommandRegistrar from the agents module.

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Upgrade spec-kit with the command shown in the error: uv tool install specify-cli --force --from git+https://github.com/github/spec-kit.git.
  2. If you maintain the preset, widen its requires.speckit_version range if the used features exist in older versions.
  3. If you cannot upgrade, find an older release of the preset compatible with your installed version.
Defensive patterns

Strategy: try-catch

Validate before calling

from packaging.version import Version
from specify_cli.presets import version_satisfies  # if exposed
required = manifest.requires_speckit_version
if not version_satisfies(speckit_version, required):
    print(f"skip: needs spec-kit {required}, installed {speckit_version}")

Try / catch

try:
    manager.install_from_directory(src, speckit_version)
except PresetCompatibilityError as e:
    # message embeds the exact upgrade command; surface it to the user verbatim
    print(e)

Prevention

When it happens

Trigger: install_from_directory / install_from_zip / install_from_archive (i.e. `specify preset add ...`) with a preset requiring e.g. ">=2.0" while the running spec-kit is 1.x. version_satisfies(speckit_version, required) returns False.

Common situations: Installing a community preset built against a newer spec-kit, or running an older specify-cli in a locked-down environment. Note the running CLI version is what matters, not the project's spec-kit scaffold version.

Related errors


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