{"record":{"id":"f980c90bc2b50b70","repo":"abhigyanpatwari/GitNexus","slug":"label-is-unreadable-path-exc","errorCode":null,"errorMessage":"{label} is unreadable: {path}: {exc}","messagePattern":"(.+?) is unreadable: (.+?): (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/evolution.py","lineNumber":92,"sourceCode":"def _require_directory_chain(root: Path, relative: Path, *, label: str) -> None:\n    \"\"\"Validate each lexical directory without erasing links via resolve().\"\"\"\n\n    _require_real_directory(root, label=label)\n    current = root\n    for part in relative.parts:\n        if part in {\"\", \".\", \"..\"}:\n            raise ValueError(f\"{label} contains an unsafe path component: {relative}\")\n        current /= part\n        _require_real_directory(current, label=label)\n\n\ndef _bounded_regular_bytes(path: Path, *, limit: int, label: str) -> bytes:\n    \"\"\"Read one bounded regular file without following its leaf link.\"\"\"\n\n    try:\n        before = path.lstat()\n    except OSError as exc:\n        raise ValueError(f\"{label} is unreadable: {path}: {exc}\") from exc\n    if stat.S_ISLNK(before.st_mode) or not stat.S_ISREG(before.st_mode):\n        raise ValueError(f\"{label} must be a regular non-symlink file: {path}\")\n    if before.st_size > limit:\n        raise ValueError(f\"{label} exceeds the bounded evidence limit\")\n\n    descriptor = os.open(path, os.O_RDONLY | getattr(os, \"O_NOFOLLOW\", 0))\n    try:\n        opened = os.fstat(descriptor)\n        if not stat.S_ISREG(opened.st_mode) or opened.st_dev != before.st_dev or opened.st_ino != before.st_ino:\n            raise ValueError(f\"{label} changed while opening: {path}\")\n        chunks: list[bytes] = []\n        remaining = limit + 1\n        while remaining > 0:\n            chunk = os.read(descriptor, min(64 * 1024, remaining))\n            if not chunk:\n                break\n            chunks.append(chunk)\n            remaining -= len(chunk)","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/evolution.py#L74-L110","documentation":"Thrown by _bounded_regular_bytes() in eval/workflow_bench/evolution.py when path.lstat() raises OSError while trying to read a candidate evidence file: the file does not exist, was removed between directory walk and read, or permission was denied. The original OSError is chained.","triggerScenarios":"candidate_overlay_payload() enumerates files, then for each source calls _bounded_regular_bytes(); if the file vanished or is unreadable in between (TOCTOU on existence), lstat raises and you get this error. Also: a file the runner has no read permission on.","commonSituations":"Concurrent writer/deleter racing with the bench reader; permissions stripped on the file after enumeration; an overlay file that is a broken symlink (lstat succeeds but is a link — different error) or was unlinked mid-run; runner uid lacks read permission.","solutions":["Make the overlay read-only and stable for the duration of the run: chmod -R a-w, ensure no concurrent process writes it.","Check file permissions (chmod/chown) — the runner's uid must have read access.","Re-stage the overlay from source if files were transient.","If racing with another process, run the bench against a private copy (cp -rL)."],"exampleFix":"# before: overlay mutated while being read\n# ValueError: candidate overlay file is unreadable: /tmp/ov/x.yaml: [Errno 2] No such file\n\n# after: snapshot + freeze before the run\ncp -rL /volatile/overlay /tmp/ov && chmod -R a-w /tmp/ov\ncandidate_overlay_payload(Path('/tmp/ov'))","handlingStrategy":"validation","validationCode":"from pathlib import Path\ndef ensure_readable_file(p: Path) -> None:\n    if not p.is_file() or not os.access(p, os.R_OK):\n        raise SystemExit(f'evidence file missing/unreadable: {p}')\n# call before _bounded_regular_bytes; also freeze the overlay to avoid races","typeGuard":"def is_unreadable_error(exc: ValueError) -> bool:\n    return 'is unreadable:' in str(exc)","tryCatchPattern":"try:\n    _bounded_regular_bytes(p, limit=L, label='candidate overlay file')\nexcept ValueError as e:\n    if is_unreadable_error(e):\n        # restage overlay read-only and retry\n        raise\n    raise","preventionTips":["Make overlays read-only for the duration of the read (chmod -R a-w).","Ensure the runner uid has read permission on every evidence file.","Do not run other writers against the overlay during the bench."],"tags":["workflow-bench","validation","path","sandbox","toctou","evolution"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}