abhigyanpatwari/GitNexus · error · ValueError
oracle parents must be real directories: {relative}
Error message
oracle parents must be real directories: {relative} What it means
Raised by _read_oracle_file when an intermediate parent directory of an oracle source is a symlink or not a directory (e.g. a regular file). The harness walks every parent component with lstat to ensure the path is composed entirely of real directories, blocking symlink-based traversal and substitution attacks against the oracle store.
Source
Thrown at eval/workflow_bench/oracle_assets.py:137
metadata = lexical.lstat()
resolved = lexical.resolve(strict=True)
except OSError as exc:
raise ValueError(f"oracle root is unavailable: {lexical}") from exc
if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode) or resolved != lexical:
raise ValueError(f"oracle root must be a real non-symlink directory: {lexical}")
return lexical
def _read_oracle_file(root: Path, relative: PurePosixPath) -> bytes:
current = root
for part in relative.parts[:-1]:
current /= part
try:
metadata = current.lstat()
except OSError as exc:
raise ValueError(f"oracle parent is unreadable: {relative}") from exc
if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):
raise ValueError(f"oracle parents must be real directories: {relative}")
path = root.joinpath(*relative.parts)
try:
before = path.lstat()
if stat.S_ISLNK(before.st_mode) or not stat.S_ISREG(before.st_mode):
raise ValueError(f"oracle source must be a bounded regular non-symlink file: {relative}")
descriptor = os.open(path, os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0))
except ValueError:
raise
except OSError as exc:
raise ValueError(f"oracle source is unreadable: {relative}") from exc
try:
opened = os.fstat(descriptor)
if (
stat.S_ISLNK(before.st_mode)
or not stat.S_ISREG(before.st_mode)
or not stat.S_ISREG(opened.st_mode)
or before.st_dev != opened.st_devView on GitHub (pinned to d540b00184)
Solutions
- Remove or replace any symlinks in the oracle source path's directory chain with real directories.
- Ensure every component except the final file is a genuine directory.
- Re-extract the oracle assets from a trusted source to eliminate tampering.
Defensive patterns
Strategy: validation
Validate before calling
import stat
from pathlib import Path
def assert_real_parents(root: Path, relative) -> None:
cur = root
for part in Path(relative).parts[:-1]:
cur /= part
md = cur.lstat()
if stat.S_ISLNK(md.st_mode) or not stat.S_ISDIR(md.st_mode):
raise ValueError(f"{cur} is not a real directory") Type guard
def parents_all_real_dirs(root, relative) -> bool:
import stat
cur = Path(root)
for part in Path(relative).parts[:-1]:
cur /= part
try:
md = cur.lstat()
except OSError:
return False
if stat.S_ISLNK(md.st_mode) or not stat.S_ISDIR(md.st_mode):
return False
return True Try / catch
try:
payload = _read_oracle_file(root, relative)
except ValueError as exc:
if "must be real directories" in str(exc):
raise SystemExit(f"Symlink/non-dir in oracle path: {relative}") from exc
raise Prevention
- Keep the oracle tree free of symlinks; audit with `find <root> -type l`.
- Materialize oracle assets from a tarball rather than a symlinked checkout.
When it happens
Trigger: An intermediate path component is a symbolic link; an intermediate component is a regular file or special device rather than a directory; the source path traverses through a symlinked directory.
Common situations: A symlink placed inside the oracle tree (intentional convenience or accidental); an oracle path like 'dir.txt/inner' where a non-directory sits mid-path; tampered or hand-edited oracle directory structure.
Related errors
- oracle root must be a real non-symlink directory: {lexical}
- oracle source must be a bounded regular non-symlink file: {r
- oracle sanitization requires a self-contained clone: {root}
- oracle sanitization requires a real self-contained clone: {r
- oracle root is unavailable: {lexical}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/913723803b4dc764.
Report an issue: GitHub.