bmad-code-org/BMAD-METHOD · error · RenderError

generation contains unexpected or missing files

Error message

generation contains unexpected or missing files: {destination}

What it means

The set of files actually on disk under the destination must equal manifest["outputs"] plus manifest.json. Extra files (added manually) or missing ones (deleted) both trip this integrity check, because the snapshot must be exactly its declared file set.

Solutions

  1. Remove stray files (e.g. .DS_Store, *.bak, *.swp) from the generation directory.
  2. Restore any deleted output, or delete the whole directory and regenerate.
  3. Add the generation tree to .gitignore or commit it untouched.

Example fix

# before: a stray .DS_Store sits inside the generation dir
# after
find _bmad/render -name '.DS_Store' -delete
# or fully regenerate
rm -rf _bmad/render/<skill>/<slug>-<hash>
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

def validate_file_set(dest: Path) -> None:
    manifest = json.loads((dest / "manifest.json").read_text(encoding="utf-8"))
    expected = set(manifest["outputs"]) | {"manifest.json"}
    actual = {p.relative_to(dest).as_posix() for p in dest.rglob("*") if p.is_file()}
    if actual != expected:
        raise SystemExit(f"file set mismatch: extra={actual-expected} missing={expected-actual}")

Prevention

When it happens

Trigger: Someone added a stray file into the generation directory, or deleted one of the recorded outputs, so actual_files != expected_files.

Common situations: Manual edits; partial cleanup; backup files (*.bak); editor swap files; OS metadata files (.DS_Store, Thumbs.db).

Related errors


AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13). Data as JSON: /api/errors/570c4490d1bb36b6. Report an issue: GitHub.

Appendix: source

Thrown at src/scripts/render_skill.py:285

    return rendered


def _verify_existing(destination: Path, manifest: dict[str, Any]) -> None:
    manifest_path = destination / "manifest.json"
    try:
        existing = json.loads(manifest_path.read_text(encoding="utf-8"))
    except (OSError, UnicodeError, json.JSONDecodeError) as error:
        raise RenderError(f"corrupt existing generation {destination}: {error}") from error
    if existing != manifest:
        raise RenderError(f"generation collision or corruption at {destination}")
    expected_files = set(manifest["outputs"]) | {"manifest.json"}
    actual_files = {
        path.relative_to(destination).as_posix()
        for path in destination.rglob("*")
        if path.is_file()
    }
    if actual_files != expected_files:
        raise RenderError(f"generation contains unexpected or missing files: {destination}")
    for name, expected_hash in manifest["outputs"].items():
        try:
            actual_hash = _hash_bytes((destination / name).read_bytes())
        except OSError as error:
            raise RenderError(f"failed to verify {destination / name}: {error}") from error
        if actual_hash != expected_hash:
            raise RenderError(f"generation output hash mismatch: {destination / name}")


def _publish(destination: Path, outputs: dict[str, bytes], manifest: dict[str, Any]) -> None:
    destination.parent.mkdir(parents=True, exist_ok=True)
    if destination.exists():
        _verify_existing(destination, manifest)
        return
    staging = Path(tempfile.mkdtemp(prefix=".staging-", dir=destination.parent))
    try:
        for name, content in outputs.items():
            path = staging / name

View on GitHub (pinned to b70486b9bd)