abhigyanpatwari/GitNexus · error · SandboxError

Compound Engineering plugin manifest is missing: {manifest_p

Error message

Compound Engineering plugin manifest is missing: {manifest_path}

What it means

_ALLOWED_PLUGIN_MANIFESTS[0] (.claude-plugin/plugin.json) is mandatory. If .claude-plugin/ is real but plugin.json does not exist (.exists() is False), the harness cannot load the plugin and aborts.

Source

Thrown at eval/workflow_bench/runtime_mounts.py:302

    return False


def _plugin_files(source: Path) -> Iterator[tuple[PurePosixPath, Path]]:
    """Yield only allowlisted plugin files in stable order."""

    manifest_root = source / ".claude-plugin"
    try:
        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):

View on GitHub (pinned to d540b00184)

Solutions

  1. Create .claude-plugin/plugin.json with the required fields (name, version).
  2. If you intended a different manifest name, also add plugin.json — the harness only relaxes this for the optional secondary manifests.

Example fix

// before: .claude-plugin/ contains only marketplace.json
// after: add .claude-plugin/plugin.json
{
  "name": "compound-engineering",
  "version": "1.2.3"
}
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def manifest_present(source: Path) -> bool:
    return (source / ".claude-plugin" / "plugin.json").exists()

Try / catch

try:
    list(_plugin_files(source))
except SandboxError as exc:
    if "manifest is missing" in str(exc):
        # add .claude-plugin/plugin.json
        ...
    raise

Prevention

When it happens

Trigger: .claude-plugin/ contains only marketplace.json (or nothing); plugin.json was renamed; the file was deleted.

Common situations: Incomplete plugin release; generator/template that emits only marketplace.json; manual cleanup that removed the wrong file.

Related errors


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