{"record":{"id":"406defc28e604593","repo":"abhigyanpatwari/GitNexus","slug":"compound-engineering-plugin-file-exceeds-the-per-f","errorCode":null,"errorMessage":"Compound Engineering plugin file exceeds the per-file limit: {path}","messagePattern":"Compound Engineering plugin file exceeds the per-file limit: (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/runtime_mounts.py","lineNumber":358,"sourceCode":"            metadata = directory.lstat()\n        except OSError as exc:\n            raise SandboxError(f\"Compound Engineering plugin component is unreadable: {directory}: {exc}\") from exc\n        if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):\n            raise SandboxError(f\"Compound Engineering plugin component must be a real directory: {directory}\")\n        yield from walk(directory, PurePosixPath(name))\n\n\ndef _bounded_plugin_bytes(path: Path) -> tuple[bytes, bool]:\n    \"\"\"Read one stable regular file without following a last-component symlink.\"\"\"\n\n    try:\n        before = path.lstat()\n    except OSError as exc:\n        raise SandboxError(f\"Compound Engineering plugin file is unreadable: {path}: {exc}\") from exc\n    if stat.S_ISLNK(before.st_mode) or not stat.S_ISREG(before.st_mode):\n        raise SandboxError(f\"Compound Engineering plugin file must be regular and non-symlink: {path}\")\n    if before.st_size > MAX_CE_PLUGIN_FILE_BYTES:\n        raise SandboxError(f\"Compound Engineering plugin file exceeds the per-file limit: {path}\")\n    descriptor = os.open(path, os.O_RDONLY | getattr(os, \"O_NOFOLLOW\", 0))\n    try:\n        opened = os.fstat(descriptor)\n        if (opened.st_dev, opened.st_ino) != (before.st_dev, before.st_ino) or not stat.S_ISREG(opened.st_mode):\n            raise SandboxError(f\"Compound Engineering plugin file changed during validation: {path}\")\n        chunks: list[bytes] = []\n        remaining = MAX_CE_PLUGIN_FILE_BYTES + 1\n        while remaining > 0:\n            chunk = os.read(descriptor, min(64 * 1024, remaining))\n            if not chunk:\n                break\n            chunks.append(chunk)\n            remaining -= len(chunk)\n        payload = b\"\".join(chunks)\n        after = os.fstat(descriptor)\n    finally:\n        os.close(descriptor)\n    if len(payload) > MAX_CE_PLUGIN_FILE_BYTES:","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/runtime_mounts.py#L340-L376","documentation":"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.","triggerScenarios":"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.","commonSituations":"Vendoring a wheel/tarball into the plugin, embedding a fixture corpus, shipping a compiled helper binary, committing a large lockfile or generated map.","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."],"exampleFix":"# before\nscripts/ce_helper  # 3.1 MiB compiled binary\n# after\nscripts/ce_helper  # stripped to 1.4 MiB via 'strip' and UPX, or replaced by a <2 MiB Python helper","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\nMAX = 2 * 1024 * 1024\nplugin = Path(\"ce-plugin\")\noversized = [(str(p), p.stat().st_size) for p in plugin.rglob(\"*\") if p.is_file() and p.stat().st_size > MAX]\nif oversized:\n    raise SystemExit(f\"files over 2 MiB: {oversized}\")","typeGuard":"from pathlib import Path\nMAX_CE_PLUGIN_FILE_BYTES = 2 * 1024 * 1024\n\ndef under_file_limit(path: Path) -> bool:\n    try:\n        return path.lstat().st_size <= MAX_CE_PLUGIN_FILE_BYTES\n    except OSError:\n        return False","tryCatchPattern":"# Pre-validate sizes; catching at run time only allows reporting:\ntry:\n    _build_ce_plugin_snapshot(config, destination_parent)\nexcept SandboxError as exc:\n    if \"per-file limit\" in str(exc):\n        log.error(\"plugin file > 2 MiB; trim and retry\")\n    raise","preventionTips":["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."],"tags":["sandbox","ce-plugin","size-limit","validation","workflow-bench"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}