github/spec-kit · error · BundlerError

Failed to remove extension '{component.id}': {exc}

Error message

Failed to remove extension '{component.id}': {exc}

What it means

During bundle removal, ExtensionManager.remove(component.id) raised an unexpected exception; the bundler wraps it as BundlerError, keeping the original message. remove_bundle's outer handler will report the partial-state detail (see error 122).

Source

Thrown at src/specify_cli/bundler/services/primitives.py:308

            )
        _assert_pinned_version(
            "Extension", component.id, component.version, info.get("version")
        )
        zip_path = catalog.download_extension(component.id)
        try:
            self._manager.install_from_zip(
                zip_path, speckit_version, priority=priority, force=force
            )
        finally:
            with contextlib.suppress(Exception):
                if zip_path.exists():
                    zip_path.unlink()

    def remove(self, component: ComponentRef) -> None:
        try:
            self._manager.remove(component.id)
        except Exception as exc:  # noqa: BLE001
            raise BundlerError(
                f"Failed to remove extension '{component.id}': {exc}"
            ) from exc


class _WorkflowKindManager:
    def __init__(self, project_root: Path, allow_network: bool) -> None:
        from ...workflows.catalog import WorkflowRegistry

        self._root = project_root
        self._allow_network = allow_network
        self._registry = WorkflowRegistry(project_root)

    def is_installed(self, component: ComponentRef) -> bool:
        try:
            return self._registry.is_installed(component.id)
        except Exception:  # noqa: BLE001
            return False

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Inspect the embedded {exc} for the concrete cause (missing path, permission).
  2. Re-sync state: reinstall the extension (`specify extension add <id>`) and then re-run the bundle remove, or remove it directly with `specify extension remove <id>`.
  3. Fix filesystem permissions and retry.
  4. Confirm cleanup with `specify bundle list` afterwards.
Defensive patterns

Strategy: try-catch

Validate before calling

from specify_cli.extensions import ExtensionManager

manager = ExtensionManager(project_root)
for c in bundle_extension_components:
    if not manager.is_installed(c.id):  # adjust to actual API
        print(f"extension {c.id} missing; state may be out of sync")

Try / catch

from specify_cli.bundler.core import BundlerError

try:
    remove_bundle(project_root, bundle_id, installer)
except BundlerError as exc:
    if "Failed to remove extension" in str(exc):
        reconcile_extension_state(str(exc.__cause__))

Prevention

When it happens

Trigger: Uninstalling a bundle whose extension component fails to remove — extension files already deleted by hand, stale .specify/extensions state, or filesystem permission errors.

Common situations: Manual deletion of an extension directory before bundle remove; extension uninstalled individually first, leaving the bundle record stale; locked files on Windows or read-only mounts.

Related errors


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