moeru-ai/airi · error · Error

Extension manifest exceeds the 1 MiB size limit.

Error message

Extension manifest exceeds the 1 MiB size limit.

What it means

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.

Solutions

  1. Shrink the manifest to under 1 MiB; move bulk data into separate asset files
  2. Remove generated/bundled content from package.json and keep only metadata
  3. Regenerate the manifest if it is corrupted

Example fix

// before
{ "name": "ext", "data": "<base64 blob of 2MB screenshot>" }
// after
{ "name": "ext" } // data moved to assets/banner.png
Defensive patterns

Strategy: validation

Validate before calling

import { stat } from 'node:fs/promises'
async function manifestWithinLimit(p: string): Promise<boolean> {
  const s = await stat(p)
  return s.size <= 1024 * 1024
}

Try / catch

try {
  await importFromDirectory(dir)
} catch (e) {
  if (e instanceof Error && e.message.includes('exceeds the 1 MiB size limit')) {
    console.warn('Manifest too large; move bulk data into separate asset files')
    return null
  }
  throw e
}

Prevention

When it happens

Trigger: package.json (or the labeled manifest) in the selected extension directory is larger than 1 MiB at inspection time.

Common situations: Bundling data/embedded assets into package.json; auto-generated manifests with lockfile-like content; a corrupted or concatenated file.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of moeru-ai/airi@438a067dde (2026-09-17). Data as JSON: /api/errors/af6101d0300d4628. Report an issue: GitHub.

Appendix: source

Thrown at apps/stage-tamagotchi/src/main/services/airi/plugins/host/directory-import.ts:137

}

async function readManifestSnapshot(path: string, expectedSize: number): Promise<Buffer> {
  const handle = await open(path, 'r')
  try {
    // One extra byte distinguishes the maximum valid manifest from a file
    // that grew past the limit after the directory walk.
    const buffer = Buffer.allocUnsafe(extensionPackageLimits.manifestBytes + 1)
    let bytesRead = 0
    while (bytesRead < buffer.byteLength) {
      const result = await handle.read(buffer, bytesRead, buffer.byteLength - bytesRead, bytesRead)
      if (result.bytesRead === 0) {
        break
      }
      bytesRead += result.bytesRead
    }

    if (bytesRead > extensionPackageLimits.manifestBytes) {
      throw new Error('Extension manifest exceeds the 1 MiB size limit.')
    }

    const finalStats = await handle.stat()
    if (!finalStats.isFile() || finalStats.size !== expectedSize || bytesRead !== expectedSize) {
      throw new Error('Extension package changed during inspection. Select the folder again.')
    }

    return buffer.subarray(0, bytesRead)
  }
  finally {
    await handle.close()
  }
}

async function inspectExtensionDirectory(sourcePath: string): Promise<InspectedExtensionDirectory> {
  const sourceStats = await lstat(sourcePath)
  if (sourceStats.isSymbolicLink() || !sourceStats.isDirectory()) {
    throw new Error(`Extension source must be a regular directory: ${sourcePath}`)

View on GitHub (pinned to 438a067dde)