{"record":{"id":"48410c30546aec5d","repo":"github/spec-kit","slug":"preset-component-id-is-not-bundled-and-network","errorCode":null,"errorMessage":"Preset '{component.id}' is not bundled and network access is disabled; re-run without --offline or install it first with 'specify preset add {component.id}'.","messagePattern":"Preset '(.+?)' is not bundled and network access is disabled; re-run without --offline or install it first with 'specify preset add (.+?)'\\.","errorType":"exception","errorClass":"BundlerError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/bundler/services/primitives.py","lineNumber":189,"sourceCode":"\n        bundled = _locate_bundled_preset(component.id)\n        if bundled is not None:\n            # Enforce the manifest pin against the bundled asset's own version,\n            # mirroring the catalog path below (the bundled path previously\n            # skipped the pin entirely).\n            _assert_pinned_version(\n                \"Preset\",\n                component.id,\n                component.version,\n                _bundled_manifest_version(bundled / \"preset.yml\", \"preset\"),\n            )\n            self._manager.install_from_directory(\n                bundled, speckit_version, priority, **({\"force\": True} if force else {})\n            )\n            return\n\n        if not self._allow_network:\n            raise BundlerError(\n                f\"Preset '{component.id}' is not bundled and network access is \"\n                f\"disabled; re-run without --offline or install it first with \"\n                f\"'specify preset add {component.id}'.\"\n            )\n\n        from ...presets import PresetCatalog\n\n        catalog = PresetCatalog(self._root)\n        info = catalog.get_pack_info(component.id)\n        if not info:\n            raise BundlerError(f\"Preset '{component.id}' not found in any catalog.\")\n        if not info.get(\"_install_allowed\", True):\n            raise BundlerError(\n                f\"Preset '{component.id}' is from a discovery-only catalog; \"\n                \"installation is not allowed.\"\n            )\n        _assert_pinned_version(\n            \"Preset\", component.id, component.version, info.get(\"version\")","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/bundler/services/primitives.py#L171-L207","documentation":"A bundle install needs to fetch a preset from the network because the preset is not bundled inside the artifact, but the bundler was constructed with allow_network=False (--offline). The error names both remedies: drop --offline, or pre-install the preset with `specify preset add <id>` so the install can proceed offline.","triggerScenarios":"Running `specify bundle install <artifact> --offline` where the artifact's bundled/ tree does not contain the preset directory, so _PresetKindManager hits the `if not self._allow_network` branch at primitives.py:187.","commonSituations":"Air-gapped or CI environments using --offline with a bundle that only pins catalog presets without vendoring them; a bundle built from a manifest-only directory where components were expected to be fetched remotely.","solutions":["Pre-install the preset in the target project first: `specify preset add <id>` (online once), then re-run the offline bundle install.","Re-run the bundle install without --offline if network is acceptable.","For a permanently offline environment, rebuild the bundle so the preset is vendored into the artifact's bundled/ directory."],"exampleFix":"specify preset add my-preset   # once, with network\nspecify bundle install my-bundle-1.0.0.zip --offline  # now succeeds","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef offline_ready(artifact_dir: Path, component_id: str) -> bool:\n    bundled = artifact_dir / \"bundled\" / \"presets\" / component_id\n    return bundled.is_dir() or preset_already_installed(project_root, component_id)","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):\n        subprocess.run([\"specify\", \"preset\", \"add\", extract_id(str(exc))], check=True)\n        install_bundle(project_root, plan, installer, allow_network=False)","preventionTips":["For offline environments, pre-install every catalog preset the bundle needs, or build bundles that vendor presets into bundled/.","Test `--offline` installs in CI with a clean project root to catch un-vendored components early.","Document which bundle components require network so operators can pre-stage them."],"tags":["bundler","offline","preset","network"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}