{"record":{"id":"64169e323480c258","repo":"moeru-ai/airi","slug":"extension-package-exceeds-the-extensionpackagelimits-entries","errorCode":null,"errorMessage":"Extension package exceeds the ${extensionPackageLimits.entries} entry limit.","messagePattern":"Extension package exceeds the (.+?) entry limit\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/stage-tamagotchi/src/main/services/airi/plugins/host/directory-import.ts","lineNumber":176,"sourceCode":"  const sourceRealPath = await realpath(sourcePath)\n  const manifestPath = join(sourceRealPath, extensionManifestFileName)\n  await assertRegularFile(manifestPath, 'Extension manifest')\n\n  const files: Array<{ path: string, relativePath: string, size: number }> = []\n  const directories = ['.']\n  const pendingDirectories = [sourceRealPath]\n  let entryCount = 0\n  let totalBytes = 0\n  while (pendingDirectories.length > 0) {\n    const directory = pendingDirectories.pop()\n    if (!directory) {\n      continue\n    }\n    const entries = await opendir(directory)\n    for await (const entry of entries) {\n      entryCount += 1\n      if (entryCount > extensionPackageLimits.entries) {\n        throw new Error(`Extension package exceeds the ${extensionPackageLimits.entries} entry limit.`)\n      }\n      const path = join(directory, entry.name)\n      const stats = await lstat(path)\n      const relativePath = relative(sourceRealPath, path)\n\n      if (stats.isSymbolicLink()) {\n        throw new Error(`Extension packages cannot contain symbolic links: ${relativePath}`)\n      }\n      if (stats.isDirectory()) {\n        directories.push(relativePath)\n        pendingDirectories.push(path)\n        continue\n      }\n      if (!stats.isFile()) {\n        throw new Error(`Extension packages can contain only files and directories: ${relativePath}`)\n      }\n      totalBytes += stats.size\n      if (totalBytes > extensionPackageLimits.totalBytes) {","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/moeru-ai/airi/blob/438a067dde47aa0bdb46c2323d1fe293dc805218/apps/stage-tamagotchi/src/main/services/airi/plugins/host/directory-import.ts#L158-L194","documentation":"During the breadth-first walk of the extension directory, every entry increments a counter; once it exceeds extensionPackageLimits.entries the import is aborted. The cap prevents pathological or hostile packages with enormous file counts from exhausting the walker.","triggerScenarios":"Calling inspectExtensionDirectory on a folder whose total file+directory entry count (recursively, including node_modules-like trees) exceeds extensionPackageLimits.entries.","commonSituations":"Importing a folder that accidentally contains node_modules, .git objects, or build-output artifacts; importing an unpacked package with thousands of small files; a generator emitted an absurdly deep/wide tree.","solutions":["Remove unneeded directories (node_modules, .git, dist caches) from the extension folder before importing.","Import only the package source/root that contains the manifest, not the whole workspace.","Ship the extension as a curated set of files and check the entry count before importing.","If the package legitimately needs more entries, split it into multiple extensions."],"exampleFix":"// before\nawait staged('my-workspace/') // includes node_modules (100k+ entries) -> throws\n// after: prune before import\nawait stageCleanup('my-workspace/') // rm -rf node_modules .git dist\nawait staged('my-workspace/')","handlingStrategy":"validation","validationCode":"import { readdir } from 'node:fs/promises'\nimport { join } from 'node:path'\nasync function countEntries(dir: string): Promise<number> {\n  let n = 0\n  for (const entry of await readdir(dir, { withFileTypes: true })) {\n    n += 1\n    if (entry.isDirectory()) n += await countEntries(join(dir, entry.name))\n  }\n  return n\n}\n// countEntries(folder) should stay below extensionPackageLimits.entries","typeGuard":null,"tryCatchPattern":"try {\n  await staged(folder)\n} catch (error) {\n  if (error instanceof Error && error.message.includes('entry limit')) {\n    showUserError('Package has too many files; remove node_modules/.git/build caches and retry.')\n    return\n  }\n  throw error\n}","preventionTips":["Prune node_modules, .git, and build caches from any folder before importing.","Import the package root containing the manifest, never a whole workspace.","Count files with `find <dir> | wc -l` before importing large packages."],"tags":["filesystem","limits","extensions","validation"],"backgroundTag":"payload-too-large","analyzedSha":"438a067dde47aa0bdb46c2323d1fe293dc805218","analyzedAt":"2026-09-17T01:14:42.644Z","contentChangedAt":"2026-09-17T01:14:42.644Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}