abhigyanpatwari/GitNexus · error · SandboxError
Compound Engineering plugin component must be a real directo
Error message
Compound Engineering plugin component must be a real directory: {directory} What it means
When a component directory exists and lstat succeeds, the harness rejects it if the mode is a symlink or not a directory. The top-level skills/, scripts/, assets/ entries themselves must be real directories — the per-entry symlink ban (error 535) covers their contents.
Source
Thrown at eval/workflow_bench/runtime_mounts.py:344
if stat.S_ISLNK(metadata.st_mode):
raise SandboxError(f"Compound Engineering plugin entries must not be symlinks: {entry.path}")
if stat.S_ISDIR(metadata.st_mode):
yield from walk(Path(entry.path), relative)
elif stat.S_ISREG(metadata.st_mode):
yield relative, Path(entry.path)
else:
raise SandboxError(f"Compound Engineering plugin entries must be regular files: {entry.path}")
for name in _ALLOWED_PLUGIN_DIRS:
directory = source / name
if not directory.exists():
continue
try:
metadata = directory.lstat()
except OSError as exc:
raise SandboxError(f"Compound Engineering plugin component is unreadable: {directory}: {exc}") from exc
if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):
raise SandboxError(f"Compound Engineering plugin component must be a real directory: {directory}")
yield from walk(directory, PurePosixPath(name))
def _bounded_plugin_bytes(path: Path) -> tuple[bytes, bool]:
"""Read one stable regular file without following a last-component symlink."""
try:
before = path.lstat()
except OSError as exc:
raise SandboxError(f"Compound Engineering plugin file is unreadable: {path}: {exc}") from exc
if stat.S_ISLNK(before.st_mode) or not stat.S_ISREG(before.st_mode):
raise SandboxError(f"Compound Engineering plugin file must be regular and non-symlink: {path}")
if before.st_size > MAX_CE_PLUGIN_FILE_BYTES:
raise SandboxError(f"Compound Engineering plugin file exceeds the per-file limit: {path}")
descriptor = os.open(path, os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0))
try:
opened = os.fstat(descriptor)
if (opened.st_dev, opened.st_ino) != (before.st_dev, before.st_ino) or not stat.S_ISREG(opened.st_mode):View on GitHub (pinned to d540b00184)
Solutions
- Check: `ls -ld <plugin_dir>/skills <plugin_dir>/scripts <plugin_dir>/assets` — modes must start with `d`, not `l`.
- Replace each symlink with a real directory: `rm <plugin_dir>/skills && cp -r <real_skills> <plugin_dir>/skills`.
- Re-extract the plugin with `tar -xhf` to dereference symlinks at extraction time.
Defensive patterns
Strategy: validation
Validate before calling
import stat
from pathlib import Path
def components_are_real_dirs(source: Path) -> bool:
for name in ("skills", "scripts", "assets"):
d = source / name
if not d.exists():
continue
try:
mode = d.lstat().st_mode
except OSError:
return False
if stat.S_ISLNK(mode) or not stat.S_ISDIR(mode):
return False
return True Try / catch
try:
list(_plugin_files(source))
except SandboxError as exc:
if "component must be a real directory" in str(exc):
# replace the symlink/file with a real directory
...
raise Prevention
- Never symlink the top-level skills/scripts/assets directories.
- Extract plugin tarballs with `tar -xhf` to dereference at extraction time.
When it happens
Trigger: <plugin_dir>/skills (or scripts, assets) is a symlink to another location, or is a regular file.
Common situations: Operator symlinked skills/ from a shared location; plugin assembled with components as links rather than real trees; monorepo workspace link leaking into the plugin.
Related errors
- Compound Engineering plugin manifest directory must be real:
- Compound Engineering plugin entries must not be symlinks: {e
- {label} target has a non-directory or symlink parent: {relat
- {label} target cannot be a symlink: {relative}
- benchmark index metadata must be regular and non-symlink: {m
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/d5b0d4697311c424.
Report an issue: GitHub.