github/spec-kit · error · BundlerError
Bundle '{target}' resolves only from a discovery-only source
Error message
Bundle '{target}' resolves only from a discovery-only source ('{resolved.source.id}'); it cannot be updated from there. Update requires an install-allowed source (FR-025). What it means
Update-side FR-025 guard: the bundle id resolves in the catalog stack, but only via a discovery-only source (resolved.install_allowed is False). Update re-downloads and re-installs components, so it requires an install-allowed origin just like install; discovery-only origins are rejected with a pointer to the rule.
Source
Thrown at src/specify_cli/commands/bundle/__init__.py:475
if all_bundles
else [bundle_id]
)
if not targets:
console.print("[yellow]No installed bundles to update.[/yellow]")
return
stack = _build_stack(project_root, offline=offline)
from ...bundler.services.adapters import DefaultPrimitiveInstaller
from ...bundler.services.installer import install_bundle
from ...bundler.services.resolver import resolve_install_plan
installer = DefaultPrimitiveInstaller(allow_network=not offline)
for target in targets:
if not any(r.bundle_id == target for r in records):
raise BundlerError(f"Bundle '{target}' is not installed.")
resolved = stack.resolve(target)
if not resolved.install_allowed:
raise BundlerError(
f"Bundle '{target}' resolves only from a discovery-only source "
f"('{resolved.source.id}'); it cannot be updated from there. "
"Update requires an install-allowed source (FR-025)."
)
manifest = _download_manifest(resolved, offline=offline)
detected = active_integration(project_root)
plan = resolve_install_plan(
manifest,
speckit_version=_speckit_version(),
active_integration=detected if detected is not None else integration,
integration_explicit=bool(integration) and detected is None,
)
install_bundle(project_root, plan, installer, manifest=manifest, refresh=True)
console.print(
f"[green]✓[/green] Updated '{_escape_markup(str(target))}' "
f"to v{_escape_markup(str(plan.version))}."
)
except BundlerError as exc:View on GitHub (pinned to bf88c9f9a8)
Solutions
- Re-point the catalog stack at an install-allowed source that carries the bundle, then re-run update.
- If the source is gone permanently, uninstall and reinstall from a concrete artifact: specify bundle install <path-to-bundle.yml | dir | .zip>.
- Operators: publish the bundle on an install-allowed source and keep the discovery index consistent.
Example fix
# before specify bundle update my-bundle # only discovery source knows it # after specify bundle uninstall my-bundle && specify bundle install ./my-bundle-1.1.0.zip
Defensive patterns
Strategy: validation
Validate before calling
resolved = stack.resolve(bundle_id)
if not resolved.install_allowed:
raise SystemExit(f"Cannot update {bundle_id} from '{resolved.source.id}' (FR-025); reinstall from an artifact") Type guard
def can_update(resolved) -> bool:
return resolved.install_allowed Try / catch
try:
bundle_update(...)
except BundlerError as exc:
if "cannot be updated from there" in str(exc):
# uninstall + reinstall from a local artifact
... Prevention
- Ensure an install-allowed source for each installed bundle stays configured.
- Keep artifact copies of bundles whose upstream mirrors may disappear.
When it happens
Trigger: specify bundle update <installed-id> where stack.resolve(<id>) hits a source registered with install_allowed=False (e.g. the bundle is indexed by a search catalog but its install mirror was removed from the stack configuration).
Common situations: A bundle moved hosts after install; catalog configuration changed so only the discovery index still lists it; corporate mirror decommissioned.
Related errors
- Preset '{component.id}' is from a discovery-only catalog; in
- Extension '{component.id}' is from a discovery-only catalog;
- Bundle '{bundle_id}' resolves only from a discovery-only sou
- Malformed catalog config at {path}: expected a mapping at th
- Unsupported catalog config schema version '{str(schema_versi
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/f39cc185a3724d15.
Report an issue: GitHub.