github/spec-kit · error · BundlerError

Workflow '{component.id}' installs from a catalog and networ

Error message

Workflow '{component.id}' installs from a catalog and network access is disabled; re-run without --offline or install it first with 'specify workflow add {component.id}'.

What it means

Workflow components are installed by delegating to `specify workflow add`, which fetches from a catalog. If the workflow is not vendored in the artifact's bundled/ tree (checked via _is_bundled) and the bundler runs with --offline, installation is refused up front, before any delegation or version assertion.

Source

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


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

    def install(self, component: ComponentRef) -> None:
        if not self._allow_network and not self._is_bundled(component.id):
            raise BundlerError(
                f"Workflow '{component.id}' installs from a catalog and network "
                f"access is disabled; re-run without --offline or install it first "
                f"with 'specify workflow add {component.id}'."
            )
        self._assert_pinned_version(component)
        from ... import workflow_add

        with _chdir(self._root):
            _delegate_command(
                "install", f"workflow '{component.id}'",
                lambda: workflow_add(component.id),
            )

    def refresh(self, component: ComponentRef) -> None:
        # workflow_add is idempotent for already-installed workflows; delegate
        # to the standard install path which handles version refresh correctly.
        self.install(component)

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Pre-install the workflow online once: `specify workflow add <id>`, then re-run the offline bundle install.
  2. Re-run the bundle install without --offline.
  3. Rebuild the bundle with the workflow vendored under bundled/ so no network is needed.

Example fix

specify workflow add my-workflow   # once, with network
specify bundle install my-bundle-1.0.0.zip --offline
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def offline_ready(artifact_dir: Path, workflow_id: str) -> bool:
    bundled = artifact_dir / "bundled" / "workflows" / workflow_id
    return bundled.is_dir() or workflow_already_installed(project_root, workflow_id)

Try / catch

from specify_cli.bundler.core import BundlerError

try:
    install_bundle(project_root, plan, installer, allow_network=False)
except BundlerError as exc:
    if "network access is disabled" in str(exc):
        subprocess.run(["specify", "workflow", "add", extract_id(str(exc))], check=True)
        install_bundle(project_root, plan, installer, allow_network=False)

Prevention

When it happens

Trigger: `specify bundle install <artifact> --offline` where the manifest includes a workflows component and the artifact does not contain the workflow locally: `not allow_network and not self._is_bundled(id)` is True at primitives.py:336.

Common situations: Offline/air-gapped CI with bundles that only pin catalog workflows; --offline chosen for determinism but the bundle expects remote fetch.

Related errors


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