{"record":{"id":"1f61705e3e8511f4","repo":"abhigyanpatwari/GitNexus","slug":"repository-root-changed-during-overlay-phase-r","errorCode":null,"errorMessage":"repository root changed during overlay {phase}: {root}","messagePattern":"repository root changed during overlay (.+?): (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"eval/workflow_bench/promotion_apply.py","lineNumber":241,"sourceCode":"    except BaseException:\n        os.close(current)\n        raise\n\n\ndef _directory_identity(metadata: os.stat_result) -> tuple[int, int, int]:\n    return metadata.st_dev, metadata.st_ino, stat.S_IFMT(metadata.st_mode)\n\n\ndef _validate_repository_root_binding(root: Path, root_descriptor: int, *, phase: str) -> None:\n    \"\"\"Prove the held root still names the repository's lexical directory.\"\"\"\n\n    flags = os.O_RDONLY | os.O_DIRECTORY | getattr(os, \"O_CLOEXEC\", 0) | getattr(os, \"O_NOFOLLOW\", 0)\n    try:\n        lexical = root.lstat()\n        resolved = root.resolve(strict=True)\n        reopened = os.open(root, flags)\n    except OSError as exc:\n        raise ValueError(f\"repository root changed during overlay {phase}: {root}\") from exc\n    try:\n        opened = os.fstat(reopened)\n        held = os.fstat(root_descriptor)\n        if (\n            stat.S_ISLNK(lexical.st_mode)\n            or not stat.S_ISDIR(lexical.st_mode)\n            or resolved != root\n            or not stat.S_ISDIR(opened.st_mode)\n            or not stat.S_ISDIR(held.st_mode)\n            or _directory_identity(lexical) != _directory_identity(opened)\n            or _directory_identity(opened) != _directory_identity(held)\n        ):\n            raise ValueError(f\"repository root changed during overlay {phase}: {root}\")\n    finally:\n        os.close(reopened)\n\n\ndef _validate_prepared_paths(","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/promotion_apply.py#L223-L259","documentation":"All errors below are raised by internal helpers of `eval/workflow_bench/promotion_apply.py` and propagate to the caller of the public entry points: `apply_promoted_overlay(overlay, repo_root, *, expected_digest, expected_target_bases)`, `destination_base_digests(overlay, repo_root)`, `committed_destination_base_digests(overlay, repo_root, *, ref)` and `freeze_overlay(overlay, destination)`. The module applies promoted skill overlays across the canonical skill tree plus its shipped mirrors (`gitnexus/skills`, `gitnexus-claude-plugin/skills`) in a TOCTOU-hardened, symlink-rejecting, descriptor-bound transaction. `_validate_repository_root_binding(root, root_descriptor, *, phase)` re-checks the root mid-transaction by calling `root.lstat()`, `root.resolve(strict=True)`, and `os.open(root, flags)` again. If any of those raises `OSError`, the root became inaccessible or was replaced while the overlay transaction was already in progress (the `phase` name appears in the message).","triggerScenarios":"Called from `_validate_prepared_paths` at preparation, pre-publication, publication, and post-apply phases; any concurrent removal/replacement/permission-change of the root during the transaction trips it.","commonSituations":"A long promotion interrupted by a checkout reset; CI timeout tearing down the workspace mid-run; operator `rm -rf` during apply; mount eviction mid-transaction.","solutions":["Ensure the repository root stays present and unchanged for the whole transaction.","Use an exclusive lock and a private, stable checkout.","Re-run from a fresh trusted clone; do not attempt partial recovery by hand."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import fcntl\nwith open(root / '.promotion.lock', 'w') as lock:\n    fcntl.flock(lock, fcntl.LOCK_EX)\n    apply_promoted_overlay(overlay, repo_root=root)","typeGuard":null,"tryCatchPattern":"except ValueError as exc:\n    if 'changed during overlay' in str(exc):\n        raise RuntimeError(f'root replaced mid-transaction at {exc}; re-run from a clean clone') from exc","preventionTips":["Keep the root stable (no reset/teardown) for the full apply window.","Hold an exclusive lock for the whole transaction.","Abort and re-clone rather than retrying in-place on a shared checkout."],"tags":["toctou","filesystem","race-condition","transaction","integrity","repository-root"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}