github/spec-kit · error · ValueError

Extension '{ext_spec}' is in the '{catalog_name}' catalog bu

Error message

Extension '{ext_spec}' is in the '{catalog_name}' catalog but installation is not allowed from that catalog

What it means

Catalogs carry an installation policy; the built-in community catalog is discovery-only (`install_allowed: false`). When the resolved extension comes from such a catalog, init refuses to download it, even though search/info can display it. This is a deliberate trust-boundary control.

Source

Thrown at src/specify_cli/commands/init.py:163

    if resolved_id != ext_spec:
        bundled_path = _locate_bundled_extension(resolved_id)
        if bundled_path is not None:
            if manager.registry.is_installed(resolved_id):
                return "already installed"
            manifest = manager.install_from_directory(bundled_path, speckit_version)
            return f"{manifest.name} v{manifest.version} installed"

    if ext_info.get("bundled") and not ext_info.get("download_url"):
        from ..extensions import REINSTALL_COMMAND

        raise ValueError(
            f"Extension '{resolved_id}' is bundled with spec-kit but not found in the installed package. "
            f"Try reinstalling spec-kit: {REINSTALL_COMMAND}"
        )

    if not ext_info.get("_install_allowed", True):
        catalog_name = ext_info.get("_catalog_name", "community")
        raise ValueError(
            f"Extension '{ext_spec}' is in the '{catalog_name}' catalog but installation is not allowed from that catalog"
        )

    zip_path = catalog.download_extension(resolved_id)
    try:
        manifest = manager.install_from_zip(zip_path, speckit_version)
    finally:
        zip_path.unlink(missing_ok=True)
    return f"{manifest.name} v{manifest.version} installed"


def _shell_quote_arg(value: str) -> str:
    """Quote *value* as one argument for the shells of the host OS.

    The Next Steps ``cd`` line is copy-pasted into whichever shell ran
    ``specify init``, so it is quoted for the host the same way
    ``_version._render_argv`` renders its copy-pasteable installer command:
    ``list2cmdline`` on Windows, ``shlex.quote`` elsewhere. The Windows branch

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Check which catalog produced the entry with extension search/info; the error names it.
  2. Use an equivalent extension from an approved/default catalog if one exists.
  3. Have an administrator curate the extension into a trusted catalog and configure `.specify/extension-catalogs.yml` with `install_allowed: true`.
  4. Only if you trust the source, install it explicitly from a local path or reviewed HTTPS URL instead of bypassing catalog policy.

Example fix

# .specify/extension-catalogs.yml (after explicit approval)
catalogs:
  - name: approved-org-catalog
    url: https://catalog.example.com/catalog.json
    priority: 1
    install_allowed: true
    description: Extensions approved by this organization
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
from specify_cli.extensions import ExtensionCatalog

def extension_install_is_allowed(ext_spec: str, project_root: Path) -> bool:
    info = ExtensionCatalog(project_root).get_extension_info(ext_spec)
    return bool(info) and bool(info.get("_install_allowed", True))

Try / catch

try:
    _install_extension_during_init(project_path, ext_spec, version)
except ValueError as exc:
    if "installation is not allowed" in str(exc):
        request_curated_catalog_entry(ext_spec)
    else:
        raise

Prevention

When it happens

Trigger: `specify init --extension <id>` resolves only from the community catalog or another catalog configured with `install_allowed: false`.

Common situations: Trying to install a community-contributed extension that has not been promoted to the default/official catalog, or adding an org catalog with discovery-only policy.

Related errors


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