{"record":{"id":"171d047d1eb63ec1","repo":"abhigyanpatwari/GitNexus","slug":"overlay-destination-parent-changed-during-phase","errorCode":null,"errorMessage":"overlay destination parent changed during {phase}: {item['target']}","messagePattern":"overlay destination parent changed during (.+?): (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"eval/workflow_bench/promotion_apply.py","lineNumber":273,"sourceCode":"    finally:\n        os.close(reopened)\n\n\ndef _validate_prepared_paths(\n    root: Path,\n    root_descriptor: int,\n    prepared: list[dict[str, Any]],\n    *,\n    phase: str,\n) -> None:\n    \"\"\"Rebind every held parent descriptor to its current lexical repo path.\"\"\"\n\n    _validate_repository_root_binding(root, root_descriptor, phase=phase)\n    for item in prepared:\n        reopened = _open_target_parent(root_descriptor, item[\"target\"])\n        try:\n            if _directory_identity(os.fstat(reopened)) != _directory_identity(os.fstat(item[\"parent_descriptor\"])):\n                raise ValueError(f\"overlay destination parent changed during {phase}: {item['target']}\")\n        finally:\n            os.close(reopened)\n    # Catch a repository-root replacement that raced the parent walk itself.\n    _validate_repository_root_binding(root, root_descriptor, phase=phase)\n\n\ndef _read_destination_at(\n    parent_descriptor: int,\n    name: str,\n    *,\n    target: PurePosixPath,\n) -> tuple[bytes, int]:\n    try:\n        before = os.stat(name, dir_fd=parent_descriptor, follow_symlinks=False)\n    except FileNotFoundError as exc:\n        raise ValueError(f\"overlay destination must already be a regular file: {target}\") from exc\n    if stat.S_ISLNK(before.st_mode) or not stat.S_ISREG(before.st_mode):\n        raise ValueError(f\"overlay destination must already be a regular file: {target}\")","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/promotion_apply.py#L255-L291","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_prepared_paths` re-opens each target's parent via `_open_target_parent` and compares its directory identity against the `parent_descriptor` captured during `_prepare_targets`. If the `(dev, ino, S_IFMT)` tuple differs, the parent directory was replaced between preparation and the revalidation at `phase`.","triggerScenarios":"A target's parent directory was replaced (rm+mkdir, mv) between the prepare pass and the pre-publication / publication / post-apply revalidation.","commonSituations":"A skill category dir recreated by another tool mid-apply; overlapping promotion or build rewriting the tree; checkout reset partway through apply.","solutions":["Ensure no process replaces target parent directories during the transaction.","Hold an exclusive lock for the whole apply window.","Re-run the full promotion from a stable, single-writer checkout."],"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 'parent changed during' in str(exc):\n        raise RuntimeError(f'target parent replaced mid-transaction at {exc}') from exc","preventionTips":["Serialize all writers to the skill mirror tree with one lock.","Re-run the entire transaction after stabilizing the tree; never resume mid-way.","Audit for tooling that recreates skill directories during promotion."],"tags":["toctou","filesystem","race-condition","transaction","overlay","integrity"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}