{"record":{"id":"117cdd0cc3dcbb42","repo":"github/spec-kit","slug":"failed-to-remove-preset-component-id-exc","errorCode":null,"errorMessage":"Failed to remove preset '{component.id}': {exc}","messagePattern":"Failed to remove preset '(.+?)': (.+?)","errorType":"exception","errorClass":"BundlerError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/bundler/services/primitives.py","lineNumber":223,"sourceCode":"            )\n        _assert_pinned_version(\n            \"Preset\", component.id, component.version, info.get(\"version\")\n        )\n        zip_path = catalog.download_pack(component.id)\n        try:\n            self._manager.install_from_zip(\n                zip_path, speckit_version, priority, **({\"force\": True} if force else {})\n            )\n        finally:\n            with contextlib.suppress(Exception):\n                if zip_path.exists():\n                    zip_path.unlink()\n\n    def remove(self, component: ComponentRef) -> None:\n        try:\n            self._manager.remove(component.id)\n        except Exception as exc:  # noqa: BLE001\n            raise BundlerError(\n                f\"Failed to remove preset '{component.id}': {exc}\"\n            ) from exc\n\n\nclass _ExtensionKindManager:\n    def __init__(self, project_root: Path, allow_network: bool) -> None:\n        from ...extensions import ExtensionManager\n\n        self._root = project_root\n        self._allow_network = allow_network\n        self._manager = ExtensionManager(project_root)\n\n    def is_installed(self, component: ComponentRef) -> bool:\n        try:\n            return self._manager.registry.is_installed(component.id)\n        except Exception:  # noqa: BLE001\n            return False\n","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/bundler/services/primitives.py#L205-L241","documentation":"During bundle removal, PresetManager.remove(component.id) raised an unexpected exception, which the bundler wraps as BundlerError with the original message preserved. The caller (remove_bundle) will then classify the removal state (see error 122) — this preset was the component that failed.","triggerScenarios":"Uninstalling a bundle whose preset component's remove() throws — preset files already deleted by hand, .specify/presets state out of sync, or permission errors on the preset directory.","commonSituations":"User manually deleted a preset directory before running bundle remove; two tools managing the same preset; read-only filesystem mount.","solutions":["Read the embedded {exc} to identify the concrete failure (missing path vs permission).","If the preset is already gone, restore state consistency: reinstall the preset (`specify preset add <id>`) then remove the bundle, or clean up its record manually.","Fix permissions on the preset directory and retry the bundle remove.","Finish with `specify bundle list` to confirm the bundle record is gone."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"from specify_cli.presets import PresetManager\n\nmanager = PresetManager(project_root)\nfor c in bundle_preset_components:\n    if not manager.is_installed(c.id):  # adjust to actual API\n        print(f\"preset {c.id} missing; state may be out of sync\")","typeGuard":null,"tryCatchPattern":"from specify_cli.bundler.core import BundlerError\n\ntry:\n    remove_bundle(project_root, bundle_id, installer)\nexcept BundlerError as exc:\n    if \"Failed to remove preset\" in str(exc):\n        # exc.__cause__ holds PresetManager.remove's original exception\n        reconcile_preset_state(str(exc.__cause__))","preventionTips":["Never delete preset directories by hand — uninstall via `specify preset remove` so records stay consistent.","Before bundle remove, verify each contributed component still exists as the records expect.","Fix the underlying {exc} (permissions/missing files) before retrying the bundle remove."],"tags":["bundler","preset","remove","wrapper-error"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}