abhigyanpatwari/GitNexus · error · SandboxError

Compound Engineering plugin component is unreadable: {direct

Error message

Compound Engineering plugin component is unreadable: {directory}: {exc}

What it means

For each name in _ALLOWED_PLUGIN_DIRS (skills, scripts, assets) that exists, the harness lstat's it before walking. OSError on that lstat (other than non-existence, which is skipped) raises this error rather than silently treating the component as missing.

Source

Thrown at eval/workflow_bench/runtime_mounts.py:342

            except OSError as exc:
                raise SandboxError(f"Compound Engineering plugin entry is unreadable: {entry.path}: {exc}") from exc
            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:

View on GitHub (pinned to d540b00184)

Solutions

  1. Grant read+execute on each component: `chmod +rX <plugin_dir>/skills <plugin_dir>/scripts <plugin_dir>/assets`.
  2. Move the plugin to a stable local filesystem and re-run.
  3. Re-extract from a clean tarball.
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def components_lstatable(source: Path) -> bool:
    for name in ("skills", "scripts", "assets"):
        d = source / name
        if not d.exists():
            continue
        try:
            d.lstat()
        except OSError:
            return False
    return True

Try / catch

try:
    list(_plugin_files(source))
except SandboxError as exc:
    if "component is unreadable" in str(exc):
        # chmod +rX the named component directory
        ...
    raise

Prevention

When it happens

Trigger: skills/ (or scripts/, assets/) exists per .exists() but lstat fails — typically a transient I/O error, broken NFS handle, or permission boundary at the directory itself.

Common situations: Restrictive ACL on a single component directory; container filesystem hiccup; lazy-unmount race.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/da15bdc1f262b8de. Report an issue: GitHub.