github/spec-kit · error · BundlerError
{kind} '{component_id}' is pinned to version {pinned} in the
Error message
{kind} '{component_id}' is pinned to version {pinned} in the bundle manifest, but the resolved version is {actual}. Update the bundle's pinned version or the source before installing. What it means
The bundle manifest pins a component to a specific version, but the version actually resolved at install time (from the bundled asset's own manifest or the catalog entry) differs. _assert_pinned_version compares via parse_version when both parse cleanly, falling back to exact string comparison, and raises to prevent silently installing something other than what the bundle was tested against.
Source
Thrown at src/specify_cli/bundler/services/primitives.py:56
Bundle manifests pin component versions for reproducibility; installing
whatever the resolved source (catalog *or* bundled asset) provides would
silently violate the pin. When the source advertises no version we cannot
enforce the pin, so installation proceeds (the source, not the bundler,
owns that gap).
"""
if not pinned or advertised is None:
return
actual = str(advertised).strip()
if not actual:
return
from ..lib.versioning import parse_version
try:
matches = parse_version(actual) == parse_version(pinned)
except BundlerError:
matches = actual == str(pinned).strip()
if not matches:
raise BundlerError(
f"{kind} '{component_id}' is pinned to version {pinned} in the bundle "
f"manifest, but the resolved version is {actual}. Update the bundle's "
"pinned version or the source before installing."
)
def _bundled_manifest_version(manifest_path: Path, root_key: str) -> str | None:
"""Best-effort read of a bundled asset's declared version from its manifest.
Returns ``None`` when the manifest is missing/unreadable/invalid, which
``_assert_pinned_version`` treats as "cannot enforce" (proceed) — matching
the catalog "advertises no version" escape hatch.
"""
try:
import yaml
data = yaml.safe_load(manifest_path.read_text(encoding="utf-8"))
if isinstance(data, dict):View on GitHub (pinned to bf88c9f9a8)
Solutions
- Decide which version is correct: if you want the resolved one, update the component's pinned version in bundle.yml and rebuild the bundle.
- If the pin is correct, refresh the bundled asset source so the artifact contains that exact version, then rebuild.
- For '1.0' vs '1.0.0' mismatches, normalize the pinned string in bundle.yml to the same format the catalog/asset advertises.
- Re-run `specify bundle validate` and `specify bundle build` after editing, then reinstall.
Example fix
# before (bundle.yml)
components:
- kind: presets
id: my-preset
version: 1.2.0 # catalog now serves 1.3.0
# after (accept the new version)
components:
- kind: presets
id: my-preset
version: 1.3.0 Defensive patterns
Strategy: validation
Validate before calling
# Before installing, confirm the pin still matches what the catalog serves
from specify_cli.presets import PresetCatalog
catalog = PresetCatalog(project_root)
info = catalog.get_pack_info(component_id)
if info and component_version and str(info.get("version", "")).strip() != component_version:
print(f"pin {component_version} != catalog {info.get('version')}; update bundle.yml") Try / catch
from specify_cli.bundler.core import BundlerError
try:
install_bundle(project_root, plan, installer)
except BundlerError as exc:
if "pinned to version" in str(exc):
# message names component, pinned, and actual; decide which to keep
reconcile_pin_and_rebuild(plan) Prevention
- Pin components to exact versions and rebuild bundles promptly after any component release you adopt.
- Run a periodic drift check comparing bundle.yml pins against catalog versions.
- Use the same version format (e.g. semver X.Y.Z) on both sides to avoid parse-fallback string mismatches.
When it happens
Trigger: Installing a bundle where component.version in bundle.yml says e.g. 1.2.0 but the catalog has 1.3.0, or the bundled preset.yml/extension.yml inside the artifact declares a different version. Also fires when the pinned string is not parseable and does not string-match the advertised value.
Common situations: A component published a new version after the bundle was built; the bundle was built by copying an older component into the artifact while pinning the newer number; hand-edited bundle.yml with a stale version; '1.0' vs '1.0.0' style mismatches when one side fails version parsing.
Related errors
- Malformed catalog config at {path}: expected a mapping at th
- Unsupported catalog config schema version '{str(schema_versi
- Malformed catalog config at {path}: 'catalogs' must be a lis
- Malformed catalog config at {path}: each catalog entry must
- A catalog url is required.
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/6a8b4b48e2734e79.
Report an issue: GitHub.