{"record":{"id":"245340dd90494a1e","repo":"github/spec-kit","slug":"step-component-id-installs-from-a-catalog-and","errorCode":null,"errorMessage":"Step '{component.id}' installs from a catalog and network access is disabled; re-run without --offline or install it first with 'specify workflow step add {component.id}'.","messagePattern":"Step '(.+?)' installs from a catalog and network access is disabled; re-run without --offline or install it first with 'specify workflow step add (.+?)'\\.","errorType":"exception","errorClass":"BundlerError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/bundler/services/primitives.py","lineNumber":395,"sourceCode":"\n\nclass _StepKindManager:\n    def __init__(self, project_root: Path, allow_network: bool) -> None:\n        from ...workflows.catalog import StepRegistry\n\n        self._root = project_root\n        self._allow_network = allow_network\n        self._registry = StepRegistry(project_root)\n\n    def is_installed(self, component: ComponentRef) -> bool:\n        try:\n            return self._registry.is_installed(component.id)\n        except Exception:  # noqa: BLE001\n            return False\n\n    def install(self, component: ComponentRef) -> None:\n        if not self._allow_network:\n            raise BundlerError(\n                f\"Step '{component.id}' installs from a catalog and network access \"\n                f\"is disabled; re-run without --offline or install it first with \"\n                f\"'specify workflow step add {component.id}'.\"\n            )\n        from ... import workflow_step_add\n\n        with _chdir(self._root):\n            _delegate_command(\n                \"install\", f\"step '{component.id}'\",\n                lambda: workflow_step_add(component.id),\n            )\n\n    def refresh(self, component: ComponentRef) -> None:\n        # Preserve an existing step until we've validated we can perform refresh.\n        # For already-installed steps, keep a backup and restore it if the\n        # remove+reinstall path fails.\n        if not (self._allow_network and self.is_installed(component)):\n            self.install(component)","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/bundler/services/primitives.py#L377-L413","documentation":"Step components have no bundled/local path at all in this bundler version — _StepKindManager.install() unconditionally requires network (there is no _is_bundled escape hatch like workflows have). With allow_network=False the install is refused before delegating to `specify workflow step add`.","triggerScenarios":"Any `specify bundle install --offline` whose manifest contains a kind: steps component. Unlike workflows, steps always fetch from a catalog, so the offline guard raises immediately at primitives.py:397.","commonSituations":"Offline CI pipelines with bundles that include steps; users assuming steps behave like workflows (which can be vendored) and hitting the stricter rule.","solutions":["Pre-install the step online once: `specify workflow step add <id>`, then re-run the offline bundle install.","Run the bundle install without --offline.","For permanently offline environments, remove the step from the bundle or request/upgrade to a specify_cli version that vendors steps into artifacts."],"exampleFix":"specify workflow step add my-step   # once, with network\nspecify bundle install my-bundle-1.0.0.zip --offline","handlingStrategy":"validation","validationCode":"# Steps have NO offline path in this version — pre-install is mandatory\nfrom specify_cli.workflows.catalog import StepRegistry\n\nregistry = StepRegistry(project_root)\nmissing = [c.id for c in plan.components if c.kind == \"steps\" and not registry.is_installed(c.id)]\nif missing and running_offline:\n    print(f\"steps require network or pre-install: {missing}\"); exit(1)","typeGuard":null,"tryCatchPattern":"from specify_cli.bundler.core import BundlerError\n\ntry:\n    install_bundle(project_root, plan, installer, allow_network=False)\nexcept BundlerError as exc:\n    if \"network access is disabled\" in str(exc) and \"Step\" in str(exc):\n        subprocess.run([\"specify\", \"workflow\", \"step\", \"add\", extract_id(str(exc))], check=True)\n        install_bundle(project_root, plan, installer, allow_network=False)","preventionTips":["Never include kind: steps components in bundles targeted at --offline runs without pre-installing them.","Pre-install every step with `specify workflow step add <id>` in offline pipelines.","Check release notes when upgrading — steps may gain a vendored/bundled path in newer specify_cli versions."],"tags":["bundler","offline","step","network"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}