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

failed to verify {destination / name}: {error}

Error message

failed to verify {destination / name}: {error}

What it means

During hash verification, reading an output file's bytes raised OSError (permission denied, file vanished between listing and read). The renderer reports which output file failed.

Source

Thrown at src/scripts/render_skill.py:290

    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
            path.parent.mkdir(parents=True, exist_ok=True)
            path.write_bytes(content)
        (staging / "manifest.json").write_bytes(
            json.dumps(manifest, ensure_ascii=False, indent=2, sort_keys=True).encode("utf-8")
            + b"\n"

View on GitHub (pinned to b70486b9bd)

Solutions

  1. Fix read permissions on the named file (chmod 644).
  2. Ensure no concurrent process touches the generation directory during render.
  3. Regenerate the directory if the file is gone.

Example fix

# before: output file mode 000 (unreadable)
# after
chmod 644 _bmad/render/<skill>/<slug>-<hash>/workflow.md
Defensive patterns

Strategy: try-catch

Validate before calling

from pathlib import Path

def ensure_outputs_readable(dest: Path, names: list[str]) -> None:
    for name in names:
        p = dest / name
        try:
            p.read_bytes()
        except OSError as e:
            raise SystemExit(f"unreadable {p}: {e}")

Try / catch

from render_skill import render, RenderError

try:
    entry = render(project_root, skill_dir)
except RenderError as e:
    if "failed to verify" in str(e):
        # fix permissions / remove blockers on the named file, then retry
        ...
    raise

Prevention

When it happens

Trigger: A file listed in the manifest became unreadable during the verification loop -- permissions changed, or a race with another process removed the file after the directory listing.

Common situations: Permission changes between run stages; concurrent modification of the generation dir; flaky or networked filesystems.

Related errors


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