{"record":{"id":"af6101d0300d4628","repo":"moeru-ai/airi","slug":"extension-manifest-exceeds-the-1-mib-size-limit","errorCode":null,"errorMessage":"Extension manifest exceeds the 1 MiB size limit.","messagePattern":"Extension manifest exceeds the 1 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":137,"sourceCode":"}\n\nasync function readManifestSnapshot(path: string, expectedSize: number): Promise<Buffer> {\n  const handle = await open(path, 'r')\n  try {\n    // One extra byte distinguishes the maximum valid manifest from a file\n    // that grew past the limit after the directory walk.\n    const buffer = Buffer.allocUnsafe(extensionPackageLimits.manifestBytes + 1)\n    let bytesRead = 0\n    while (bytesRead < buffer.byteLength) {\n      const result = await handle.read(buffer, bytesRead, buffer.byteLength - bytesRead, bytesRead)\n      if (result.bytesRead === 0) {\n        break\n      }\n      bytesRead += result.bytesRead\n    }\n\n    if (bytesRead > extensionPackageLimits.manifestBytes) {\n      throw new Error('Extension manifest exceeds the 1 MiB size limit.')\n    }\n\n    const finalStats = await handle.stat()\n    if (!finalStats.isFile() || finalStats.size !== expectedSize || bytesRead !== expectedSize) {\n      throw new Error('Extension package changed during inspection. Select the folder again.')\n    }\n\n    return buffer.subarray(0, bytesRead)\n  }\n  finally {\n    await handle.close()\n  }\n}\n\nasync function inspectExtensionDirectory(sourcePath: string): Promise<InspectedExtensionDirectory> {\n  const sourceStats = await lstat(sourcePath)\n  if (sourceStats.isSymbolicLink() || !sourceStats.isDirectory()) {\n    throw new Error(`Extension source must be a regular directory: ${sourcePath}`)","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/moeru-ai/airi/blob/438a067dde47aa0bdb46c2323d1fe293dc805218/apps/stage-tamagotchi/src/main/services/airi/plugins/host/directory-import.ts#L119-L155","documentation":"readManifestSnapshot reads up to the manifest size limit (1 MiB) and throws if it read more bytes than extensionPackageLimits.manifestBytes. Huge manifests are treated as invalid packages, both to bound memory and to guard against pathological or malicious inputs.","triggerScenarios":"package.json (or the labeled manifest) in the selected extension directory is larger than 1 MiB at inspection time.","commonSituations":"Bundling data/embedded assets into package.json; auto-generated manifests with lockfile-like content; a corrupted or concatenated file.","solutions":["Shrink the manifest to under 1 MiB; move bulk data into separate asset files","Remove generated/bundled content from package.json and keep only metadata","Regenerate the manifest if it is corrupted"],"exampleFix":"// before\n{ \"name\": \"ext\", \"data\": \"<base64 blob of 2MB screenshot>\" }\n// after\n{ \"name\": \"ext\" } // data moved to assets/banner.png","handlingStrategy":"validation","validationCode":"import { stat } from 'node:fs/promises'\nasync function manifestWithinLimit(p: string): Promise<boolean> {\n  const s = await stat(p)\n  return s.size <= 1024 * 1024\n}","typeGuard":null,"tryCatchPattern":"try {\n  await importFromDirectory(dir)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('exceeds the 1 MiB size limit')) {\n    console.warn('Manifest too large; move bulk data into separate asset files')\n    return null\n  }\n  throw e\n}","preventionTips":["Keep package.json metadata-only; move data/binary blobs into assets","Check manifest size before offering a directory for import","Reject auto-generated bloated manifests in your packaging pipeline"],"tags":["file-size","limit","manifest"],"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"}