abhigyanpatwari/GitNexus · error · SandboxError
Compound Engineering plugin file exceeds the per-file limit:
Error message
Compound Engineering plugin file exceeds the per-file limit: {path} What it means
Pre-read guard in _bounded_plugin_bytes: a plugin file's lstat size already exceeds MAX_CE_PLUGIN_FILE_BYTES (2 MiB). The harness bounds each file so the snapshot cannot house an oversized blob and so the read loop has a known upper bound. This is the fast-path rejection before opening the descriptor.
Source
Thrown at eval/workflow_bench/runtime_mounts.py:358
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:
opened = os.fstat(descriptor)
if (opened.st_dev, opened.st_ino) != (before.st_dev, before.st_ino) or not stat.S_ISREG(opened.st_mode):
raise SandboxError(f"Compound Engineering plugin file changed during validation: {path}")
chunks: list[bytes] = []
remaining = MAX_CE_PLUGIN_FILE_BYTES + 1
while remaining > 0:
chunk = os.read(descriptor, min(64 * 1024, remaining))
if not chunk:
break
chunks.append(chunk)
remaining -= len(chunk)
payload = b"".join(chunks)
after = os.fstat(descriptor)
finally:
os.close(descriptor)
if len(payload) > MAX_CE_PLUGIN_FILE_BYTES:View on GitHub (pinned to d540b00184)
Solutions
- Identify the file: 'find <plugin_dir> -type f -size +2M' and shrink or remove it.
- Split a large dataset into chunks under 2 MiB each and load them by hash at runtime.
- Move bulky assets out of the plugin and fetch them with a pinned, hashed download inside the skill (the plugin only carries the fetcher).
- Strip vendor bundles and re-add only the slices the skill actually imports.
Example fix
# before scripts/ce_helper # 3.1 MiB compiled binary # after scripts/ce_helper # stripped to 1.4 MiB via 'strip' and UPX, or replaced by a <2 MiB Python helper
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
MAX = 2 * 1024 * 1024
plugin = Path("ce-plugin")
oversized = [(str(p), p.stat().st_size) for p in plugin.rglob("*") if p.is_file() and p.stat().st_size > MAX]
if oversized:
raise SystemExit(f"files over 2 MiB: {oversized}") Type guard
from pathlib import Path
MAX_CE_PLUGIN_FILE_BYTES = 2 * 1024 * 1024
def under_file_limit(path: Path) -> bool:
try:
return path.lstat().st_size <= MAX_CE_PLUGIN_FILE_BYTES
except OSError:
return False Try / catch
# Pre-validate sizes; catching at run time only allows reporting:
try:
_build_ce_plugin_snapshot(config, destination_parent)
except SandboxError as exc:
if "per-file limit" in str(exc):
log.error("plugin file > 2 MiB; trim and retry")
raise Prevention
- Keep each plugin file under 2 MiB; strip binaries and split datasets.
- CI gate: 'find <plugin_dir> -type f -size +2M' must be empty.
- Avoid embedding models/media; reference them by hash and fetch at runtime.
When it happens
Trigger: Any single file under skills/, scripts/, assets/, or .claude-plugin whose size is greater than 2 * 1024 * 1024 bytes. Typical offenders: bundled binaries in scripts/, large JSON/dataset dumps in assets/, minified vendor bundles shipped with a skill.
Common situations: Vendoring a wheel/tarball into the plugin, embedding a fixture corpus, shipping a compiled helper binary, committing a large lockfile or generated map.
Related errors
- Compound Engineering plugin exceeds the total byte limit
- {label} exceeds the bounded evidence limit
- transcript artifact exceeds the bounded run-output limit
- Compound Engineering plugin file must be regular and non-sym
- Compound Engineering plugin path exceeds the byte limit: {re
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/406defc28e604593.
Report an issue: GitHub.