{"record":{"id":"570c4490d1bb36b6","repo":"bmad-code-org/BMAD-METHOD","slug":"generation-contains-unexpected-or-missing-files","errorCode":null,"errorMessage":"generation contains unexpected or missing files: {destination}","messagePattern":"generation contains unexpected or missing files: (.+?)","errorType":"exception","errorClass":"RenderError","httpStatus":null,"severity":"error","filePath":"src/scripts/render_skill.py","lineNumber":285,"sourceCode":"    return rendered\n\n\ndef _verify_existing(destination: Path, manifest: dict[str, Any]) -> None:\n    manifest_path = destination / \"manifest.json\"\n    try:\n        existing = json.loads(manifest_path.read_text(encoding=\"utf-8\"))\n    except (OSError, UnicodeError, json.JSONDecodeError) as error:\n        raise RenderError(f\"corrupt existing generation {destination}: {error}\") from error\n    if existing != manifest:\n        raise RenderError(f\"generation collision or corruption at {destination}\")\n    expected_files = set(manifest[\"outputs\"]) | {\"manifest.json\"}\n    actual_files = {\n        path.relative_to(destination).as_posix()\n        for path in destination.rglob(\"*\")\n        if path.is_file()\n    }\n    if actual_files != expected_files:\n        raise RenderError(f\"generation contains unexpected or missing files: {destination}\")\n    for name, expected_hash in manifest[\"outputs\"].items():\n        try:\n            actual_hash = _hash_bytes((destination / name).read_bytes())\n        except OSError as error:\n            raise RenderError(f\"failed to verify {destination / name}: {error}\") from error\n        if actual_hash != expected_hash:\n            raise RenderError(f\"generation output hash mismatch: {destination / name}\")\n\n\ndef _publish(destination: Path, outputs: dict[str, bytes], manifest: dict[str, Any]) -> None:\n    destination.parent.mkdir(parents=True, exist_ok=True)\n    if destination.exists():\n        _verify_existing(destination, manifest)\n        return\n    staging = Path(tempfile.mkdtemp(prefix=\".staging-\", dir=destination.parent))\n    try:\n        for name, content in outputs.items():\n            path = staging / name","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/bmad-code-org/BMAD-METHOD/blob/b70486b9bdcb0a404d329e2a763b57964e7f1360/src/scripts/render_skill.py#L267-L303","documentation":"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.","triggerScenarios":"Someone added a stray file into the generation directory, or deleted one of the recorded outputs, so actual_files != expected_files.","commonSituations":"Manual edits; partial cleanup; backup files (*.bak); editor swap files; OS metadata files (.DS_Store, Thumbs.db).","solutions":["Remove stray files (e.g. .DS_Store, *.bak, *.swp) from the generation directory.","Restore any deleted output, or delete the whole directory and regenerate.","Add the generation tree to .gitignore or commit it untouched."],"exampleFix":"# before: a stray .DS_Store sits inside the generation dir\n# after\nfind _bmad/render -name '.DS_Store' -delete\n# or fully regenerate\nrm -rf _bmad/render/<skill>/<slug>-<hash>","handlingStrategy":"validation","validationCode":"import json\nfrom pathlib import Path\n\ndef validate_file_set(dest: Path) -> None:\n    manifest = json.loads((dest / \"manifest.json\").read_text(encoding=\"utf-8\"))\n    expected = set(manifest[\"outputs\"]) | {\"manifest.json\"}\n    actual = {p.relative_to(dest).as_posix() for p in dest.rglob(\"*\") if p.is_file()}\n    if actual != expected:\n        raise SystemExit(f\"file set mismatch: extra={actual-expected} missing={expected-actual}\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep generated dirs free of stray files (.DS_Store, *.bak, swap files).","Configure editors/OS to not drop metadata into generated trees.","If a file must be removed, delete the whole generation and regenerate."],"tags":["python","manifest","filesystem","idempotency","integrity"],"backgroundTag":null,"analyzedSha":"b70486b9bdcb0a404d329e2a763b57964e7f1360","analyzedAt":"2026-08-13T01:21:12.247Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}