{"record":{"id":"7eccf6bdfbc00c17","repo":"moeru-ai/airi","slug":"extension-package-exceeds-the-512-mib-size-limit","errorCode":null,"errorMessage":"Extension package exceeds the 512 MiB size limit.","messagePattern":"Extension package exceeds the 512 MiB size limit\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/stage-tamagotchi/src/main/services/airi/plugins/host/directory-import.ts","lineNumber":195,"sourceCode":"      }\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) {\n        throw new Error('Extension package exceeds the 512 MiB size limit.')\n      }\n      files.push({ path, relativePath, size: stats.size })\n    }\n  }\n\n  directories.sort()\n  files.sort((left, right) => left.relativePath.localeCompare(right.relativePath))\n\n  const manifestRelativePath = relative(sourceRealPath, manifestPath)\n  const manifestFile = files.find(file => file.relativePath === manifestRelativePath)\n  if (!manifestFile) {\n    throw new Error(`Extension manifest does not exist: ${manifestPath}`)\n  }\n  if (manifestFile.size > extensionPackageLimits.manifestBytes) {\n    throw new Error('Extension manifest exceeds the 1 MiB size limit.')\n  }\n\n  // The manifest remains the only retained byte snapshot because the preview","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/moeru-ai/airi/blob/438a067dde47aa0bdb46c2323d1fe293dc805218/apps/stage-tamagotchi/src/main/services/airi/plugins/host/directory-import.ts#L177-L213","documentation":"During the walk, each regular file's size is accumulated; once the total exceeds extensionPackageLimits.totalBytes (512 MiB) the import is aborted. The cap bounds memory and copy cost of staging an extension package.","triggerScenarios":"Calling inspectExtensionDirectory on a folder whose cumulative regular-file byte size exceeds 512 MiB.","commonSituations":"Accidentally importing a folder that contains large build artifacts, videos, model weights, or bundled binaries; including node_modules or .git packs; shipping unoptimized assets alongside the extension code.","solutions":["Remove large non-essential files (videos, weights, archives) from the folder.","Exclude .git, node_modules, and build caches before importing.","Compress or minify large assets, or reference them by URL instead of bundling.","Split the package: keep the extension code small and host heavy assets separately."],"exampleFix":"// before\nawait staged('my-ext/') // contains 800 MiB of model weights -> throws\n// after\n// rm my-ext/weights.bin; host weights remotely\nawait staged('my-ext/')","handlingStrategy":"validation","validationCode":"import { readdir, stat } from 'node:fs/promises'\nimport { join } from 'node:path'\nasync function totalBytes(dir: string): Promise<number> {\n  let total = 0\n  for (const entry of await readdir(dir, { withFileTypes: true })) {\n    const p = join(dir, entry.name)\n    if (entry.isFile()) total += (await stat(p)).size\n    else if (entry.isDirectory()) total += await totalBytes(p)\n  }\n  return total\n}\n// totalBytes(folder) must stay under 512 MiB (extensionPackageLimits.totalBytes)","typeGuard":null,"tryCatchPattern":"try {\n  await staged(folder)\n} catch (error) {\n  if (error instanceof Error && error.message.includes('512 MiB')) {\n    showUserError('Package is too large; remove or externalize large assets.')\n    return\n  }\n  throw error\n}","preventionTips":["Audit package size with `du -sh <dir>` before importing.","Keep large media/weights out of the extension bundle; host them remotely.","Exclude .git and node_modules — packfiles alone can exceed the limit."],"tags":["filesystem","limits","extensions","size-limit"],"backgroundTag":"file-size-limit-exceeded","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"}