github/spec-kit · error · BundlerError

Refusing to build an invalid manifest. Run 'specify bundle v

Error message

Refusing to build an invalid manifest. Run 'specify bundle validate' and fix:
  - {report.errors}

What it means

build_bundle() ran validate_manifest() on the parsed manifest and it reported one or more errors, so the build is refused. The message embeds every validation error as a bullet list and points at `specify bundle validate` for the interactive path. No zip artifact is created.

Source

Thrown at src/specify_cli/bundler/services/packager.py:54

    output_dir: Path | None = None,
) -> BuildResult:
    bundle_dir = Path(bundle_dir).resolve()
    manifest_path = bundle_dir / "bundle.yml"
    if not manifest_path.exists():
        raise BundlerError(f"No bundle.yml found in '{bundle_dir}'.")

    # The artifact contract requires a human-facing README.md alongside the
    # manifest; refuse early rather than publish a bundle with no description.
    if not (bundle_dir / "README.md").exists():
        raise BundlerError(
            f"No README.md found in '{bundle_dir}'. Every bundle must ship a "
            "README.md describing it."
        )

    manifest = BundleManifest.from_file(manifest_path)
    report = validate_manifest(manifest)
    if not report.ok:
        raise BundlerError(
            "Refusing to build an invalid manifest. Run 'specify bundle validate' "
            "and fix:\n  - " + "\n  - ".join(report.errors)
        )

    out_dir = Path(output_dir).resolve() if output_dir else bundle_dir
    out_dir.mkdir(parents=True, exist_ok=True)
    artifact_name = f"{manifest.bundle.id}-{manifest.bundle.version}.zip"
    artifact_path = out_dir / artifact_name
    # Defense in depth: even though validate_manifest() rejects unsafe ids, make
    # sure a crafted id cannot push the artifact outside the output directory.
    ensure_within(out_dir, artifact_path)

    # If the output dir lives inside the bundle, skip its whole subtree so
    # previously-built artifacts are never re-packaged (keeps builds
    # reproducible and bounded).
    skip_dir = out_dir if out_dir != bundle_dir and _is_within(bundle_dir, out_dir) else None
    # Also skip any prior build artifact for this bundle (e.g. an older
    # <id>-<version>.zip sitting next to bundle.yml), not just the current one.

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Run `specify bundle validate <bundle_dir>` and fix each listed error — the bullets in this same message are the validator output.
  2. Check required fields exist: bundle id, version, and a well-formed components list.
  3. Compare against a known-good bundle.yml from an existing bundle or the template.
  4. If the error names a component kind, use only kinds the bundler supports (presets, extensions, workflows, steps).

Example fix

# before (bundle.yml)
bundle:
  id: my-bundle
  # version missing

# after
bundle:
  id: my-bundle
  version: 1.0.0
Defensive patterns

Strategy: validation

Validate before calling

from specify_cli.bundler.services.packager import build_bundle
from specify_cli.bundler.core import BundleManifest
from specify_cli.bundler.validation import validate_manifest  # adjust import to repo layout

report = validate_manifest(BundleManifest.from_file(bundle_dir / "bundle.yml"))
if not report.ok:
    print("\n  - ".join(report.errors)); exit(1)
build_bundle(bundle_dir)

Try / catch

from specify_cli.bundler.core import BundlerError

try:
    build_bundle(bundle_dir)
except BundlerError as exc:
    if "invalid manifest" in str(exc):
        # exc message already lists every validator error line by line
        log.error("manifest invalid:\n%s", exc)

Prevention

When it happens

Trigger: A bundle.yml with schema violations: missing required fields (id/version/components), malformed component refs, invalid versions, or unsafe ids that validate_manifest() rejects. The check fires before out_dir.mkdir and zip creation.

Common situations: Hand-edited manifest with a typo or wrong indentation; component entry referencing an unknown kind; version string not matching the expected format; bundle authored against an older schema after a spec-kit upgrade.

Related errors


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