abhigyanpatwari/GitNexus · error · SandboxError

Compound Engineering plugin directory is unreadable: {direct

Error message

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

What it means

Inside the recursive walk() over skills/scripts/assets, os.scandir() failure on any directory raises SandboxError with this message. The harness will not silently skip an unreadable subtree.

Source

Thrown at eval/workflow_bench/runtime_mounts.py:317

    required_manifest = _ALLOWED_PLUGIN_MANIFESTS[0]
    manifest_path = source / Path(*required_manifest.parts)
    if not manifest_path.exists():
        raise SandboxError(f"Compound Engineering plugin manifest is missing: {manifest_path}")
    for relative in _ALLOWED_PLUGIN_MANIFESTS:
        candidate = source / Path(*relative.parts)
        if candidate.exists():
            yield relative, candidate

    skills = source / "skills"
    if not skills.exists():
        raise SandboxError(f"Compound Engineering plugin skills directory is missing: {skills}")

    def walk(directory: Path, relative_dir: PurePosixPath) -> Iterator[tuple[PurePosixPath, Path]]:
        try:
            with os.scandir(directory) as scanned:
                entries = sorted(scanned, key=lambda entry: entry.name)
        except OSError as exc:
            raise SandboxError(f"Compound Engineering plugin directory is unreadable: {directory}: {exc}") from exc
        for entry in entries:
            relative = relative_dir / entry.name
            if _is_forbidden_plugin_path(relative):
                continue
            try:
                metadata = entry.stat(follow_symlinks=False)
            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:

View on GitHub (pinned to d540b00184)

Solutions

  1. Grant read+execute on the whole tree: `chmod -R +rX <plugin_dir>`.
  2. Re-extract the plugin from a clean tarball to eliminate ACL drift.
  3. Ensure no process is modifying the plugin source while the snapshot is being built.
Defensive patterns

Strategy: validation

Validate before calling

import os
from pathlib import Path

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

Try / catch

try:
    list(_plugin_files(source))
except SandboxError as exc:
    if "directory is unreadable" in str(exc):
        # chmod -R +rX the plugin source, or copy to a stable local path
        ...
    raise

Prevention

When it happens

Trigger: Permission denied (EACCES) on a subdirectory under skills/, scripts/, or assets/; I/O error (EIO) on the underlying filesystem; directory removed mid-scan.

Common situations: Restrictive ACLs applied to part of the plugin tree; container with read-only bind mounts that omit execute permission; concurrent modification during snapshot build.

Related errors


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