abhigyanpatwari/GitNexus · error · SandboxError

Compound Engineering plugin skills directory is missing: {sk

Error message

Compound Engineering plugin skills directory is missing: {skills}

What it means

_plugin_files() requires a top-level skills/ directory in the plugin source. It is the first of the _ALLOWED_PLUGIN_DIRS and is checked explicitly before walking because CE skills are mandatory for the comparator arms.

Source

Thrown at eval/workflow_bench/runtime_mounts.py:310

        manifest_root_metadata = manifest_root.lstat()
    except OSError as exc:
        raise SandboxError(
            f"Compound Engineering plugin manifest directory is unavailable: {manifest_root}: {exc}"
        ) from exc
    if stat.S_ISLNK(manifest_root_metadata.st_mode) or not stat.S_ISDIR(manifest_root_metadata.st_mode):
        raise SandboxError(f"Compound Engineering plugin manifest directory must be real: {manifest_root}")
    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):

View on GitHub (pinned to d540b00184)

Solutions

  1. Create skills/ and populate it with the required SKILL.md files (ce-plan, ce-work, ce-code-review).
  2. Verify you pointed --ce-plugin-dir at the plugin root, not a subdirectory.
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def skills_dir_present(source: Path) -> bool:
    return (source / "skills").exists()

Try / catch

try:
    list(_plugin_files(source))
except SandboxError as exc:
    if "skills directory is missing" in str(exc):
        # create skills/ with the required SKILL.md files
        ...
    raise

Prevention

When it happens

Trigger: source/skills does not exist (.exists() is False) when _plugin_files() is called.

Common situations: Plugin assembled from a subset of directories; generator run that skipped skills; wrong source directory passed to --ce-plugin-dir.

Related errors


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