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

  1. Re-point the catalog stack at an install-allowed source that carries the bundle, then re-run update.
  2. If the source is gone permanently, uninstall and reinstall from a concrete artifact: specify bundle install <path-to-bundle.yml | dir | .zip>.
  3. 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

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


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