{"record":{"id":"d978a6ae5765bbb3","repo":"stablyai/orca","slug":"plugin-exceeds-the-max-plugin-total-bytes-byte","errorCode":null,"errorMessage":"plugin exceeds the ${MAX_PLUGIN_TOTAL_BYTES}-byte limit","messagePattern":"plugin exceeds the (.+?)-byte limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/scripts/verify-packaged-plugin-resources.cjs","lineNumber":40,"sourceCode":"    for (const entry of entries) {\n      if (directory === root && entry.name === '.git') {\n        continue\n      }\n      const entryPath = join(directory, entry.name)\n      const metadata = lstatSync(entryPath)\n      entriesVisited += 1\n      if (entriesVisited > MAX_PLUGIN_FILES) {\n        throw new Error(`plugin exceeds the ${MAX_PLUGIN_FILES}-entry limit`)\n      }\n      if (metadata.isSymbolicLink()) {\n        throw new Error(`packaged plugin contains a symlink: ${relative(root, entryPath)}`)\n      }\n      if (metadata.isDirectory()) {\n        visit(entryPath)\n      } else if (metadata.isFile()) {\n        totalBytes += metadata.size\n        if (totalBytes > MAX_PLUGIN_TOTAL_BYTES) {\n          throw new Error(`plugin exceeds the ${MAX_PLUGIN_TOTAL_BYTES}-byte limit`)\n        }\n        files.push({ path: entryPath, size: metadata.size })\n      } else {\n        throw new Error(`packaged plugin contains an unsupported entry: ${entryPath}`)\n      }\n    }\n  }\n  visit(root)\n  const hash = createHash('sha256').update('orca-plugin-tree-v1\\0')\n  for (const file of files) {\n    const relativePath = relative(root, file.path).replaceAll('\\\\', '/')\n    hashLength(hash, Buffer.byteLength(relativePath, 'utf8'))\n    hash.update(relativePath, 'utf8')\n    hashLength(hash, file.size)\n    hash.update(readFileSync(file.path))\n  }\n  return hash.digest('hex')\n}","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/verify-packaged-plugin-resources.cjs#L22-L58","documentation":"Thrown by the packaged plugin resource verifier when the cumulative byte size of all files in a single plugin tree exceeds MAX_PLUGIN_TOTAL_BYTES (50 MiB, defined as 50 * 1024 * 1024 at line 6). The counter accumulates metadata.size for every regular file and throws immediately when totalBytes crosses the threshold. This prevents oversized plugins from bloating the installer and slowing downloads.","triggerScenarios":"hashPackagedPluginTree(root) accumulates more than 50 MiB across all files in a single plugin. Typically caused by packaging binary assets, large data files, source maps, or unoptimized bundles.","commonSituations":"A plugin bundles binary assets (images, fonts, WASM files) that push it over 50 MiB; source maps (.map files) from the build are included in the package; a large third-party dependency was bundled without tree-shaking; test data or fixtures were not excluded.","solutions":["Identify the largest files in the plugin: du -ah <pluginRoot> | sort -rh | head -20.","Exclude source maps from the packaged plugin if they're not needed at runtime.","Optimize or compress binary assets (images, fonts); consider lazy-loading large assets from a CDN instead of bundling them.","If the plugin legitimately exceeds 50 MiB, raise MAX_PLUGIN_TOTAL_BYTES — but review whether all content is necessary first."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before packaging, measure total size of the plugin directory.\nconst { execSync } = require('node:child_process')\n\nfunction preCheckPluginSize(pluginRoot, maxBytes = 50 * 1024 * 1024) {\n  const output = execSync(`du -sb ${JSON.stringify(pluginRoot)}`, {\n    encoding: 'utf8'\n  })\n  const bytes = parseInt(output.split(/\\s+/)[0], 10)\n  return { ok: bytes <= maxBytes, bytes, maxBytes }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Exclude source maps from packaged plugins when they're not needed at runtime.","Optimize binary assets (images, fonts, WASM) before packaging; use compression or lower resolution where acceptable.","Monitor plugin size trends in CI to catch size regressions early before they hit the 50 MiB limit."],"tags":["plugin-packaging","size-limit","ci-gate","resource-verification"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}