abhigyanpatwari/GitNexus · error · SandboxError

Compound Engineering plugin manifest is invalid: {exc}

Error message

Compound Engineering plugin manifest is invalid: {exc}

What it means

Manifest parse guard in _build_ce_plugin_snapshot. After all files are copied, the harness reads <root>/.claude-plugin/plugin.json; if the read or json.loads raises OSError, UnicodeError, or json.JSONDecodeError, the manifest is unusable and the snapshot is rejected. The error wraps the underlying exception via 'from exc'.

Source

Thrown at eval/workflow_bench/runtime_mounts.py:453

            _write_snapshot_file(
                root / Path(*relative.parts),
                payload,
                executable=executable,
            )
            entries.append(
                {
                    "path": relative_text,
                    "sha256": hashlib.sha256(payload).hexdigest(),
                    "size": len(payload),
                    "executable": executable,
                }
            )

        manifest_path = root / ".claude-plugin" / "plugin.json"
        try:
            plugin_manifest = json.loads(manifest_path.read_text())
        except (OSError, UnicodeError, json.JSONDecodeError) as exc:
            raise SandboxError(f"Compound Engineering plugin manifest is invalid: {exc}") from exc
        if not isinstance(plugin_manifest, dict) or plugin_manifest.get("name") != "compound-engineering":
            raise SandboxError("CE comparator requires the compound-engineering plugin manifest")
        if plugin_manifest.get("version") != config.version:
            raise SandboxError(
                "Compound Engineering plugin version mismatch: "
                f"expected {config.version}, got {plugin_manifest.get('version')!r}"
            )
        for skill in ("ce-plan", "ce-work", "ce-code-review"):
            if not (root / "skills" / skill / "SKILL.md").is_file():
                raise SandboxError(f"Compound Engineering plugin is missing required skill: {skill}")

        canonical_manifest = json.dumps(
            {
                "schema_version": CE_PLUGIN_MANIFEST_SCHEMA_VERSION,
                "files": entries,
            },
            sort_keys=True,
            separators=(",", ":"),

View on GitHub (pinned to d540b00184)

Solutions

  1. Verify the source has the file: 'test -f <plugin_dir>/.claude-plugin/plugin.json && python -c "import json,sys; json.load(open(sys.argv[1]))" <plugin_dir>/.claude-plugin/plugin.json'.
  2. Confirm --ce-plugin-dir points at the plugin root (the parent of .claude-plugin), not a subdirectory.
  3. Re-encode the manifest as UTF-8 without BOM and validate with a strict JSON parser (no comments, no trailing commas).
  4. Check the build pipeline is not stripping .claude-plugin/ (e.g. an over-eager clean step or .gitignore).

Example fix

// before: .claude-plugin/plugin.json with trailing comma
{ "name": "compound-engineering", "version": "1.0.0", }
// after
{ "name": "compound-engineering", "version": "1.0.0" }
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

plugin = Path("ce-plugin")
manifest = plugin / ".claude-plugin" / "plugin.json"
if not manifest.is_file():
    raise SystemExit(f"missing manifest: {manifest}")
try:
    data = manifest.read_text(encoding="utf-8")
    json.loads(data)
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
    raise SystemExit(f"invalid manifest: {exc}")

Type guard

import json
from pathlib import Path

def manifest_parses(plugin_dir: Path) -> bool:
    m = plugin_dir / ".claude-plugin" / "plugin.json"
    try:
        json.loads(m.read_text(encoding="utf-8"))
        return True
    except (OSError, UnicodeError, json.JSONDecodeError):
        return False

Try / catch

try:
    snapshot = _build_ce_plugin_snapshot(config, destination_parent)
except SandboxError as exc:
    if "manifest is invalid" in str(exc):
        log.error("plugin.json missing/invalid; fix and retry")
    raise

Prevention

When it happens

Trigger: .claude-plugin/plugin.json is missing (OSError), not valid UTF-8 (UnicodeDecodeError, a UnicodeError subclass), truncated, or syntactically invalid JSON (JSONDecodeError). Note the snapshot root is the harness's staging dir, so this reflects what was actually copied from the source.

Common situations: Plugin source has no .claude-plugin/plugin.json (wrong directory passed to --ce-plugin-dir); file is BOM/latin-1 encoded; trailing-comma or comment in JSON5 style; file excluded by a build step or .gitignore so it never ships.

Related errors


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