nexu-io/open-design · error · Error

zip file too large: ${relPath}

Error message

zip file too large: ${relPath}

What it means

Thrown by `importClaudeDesignZip` when a central-directory entry's declared `uncompressedSize` exceeds `MAX_FILE_BYTES` (25 MiB). This is the pre-decode size guard, evaluated before the entry body is inflated.

Source

Thrown at apps/daemon/src/design/claude-design-import.ts:36

  uncompressedSize: number;
  localOffset: number;
  isDirectory: boolean;
};

type ImportedFile = { path: string; body: Buffer };

export async function importClaudeDesignZip(zipPath: string, projectDir: string) {
  const zip = await readFile(zipPath);
  const entries = readCentralDirectory(zip);
  const files: ImportedFile[] = [];
  let totalBytes = 0;

  for (const entry of entries) {
    if (entry.isDirectory) continue;
    if (files.length >= MAX_FILES) throw new Error('zip contains too many files');
    const relPath = sanitizeZipPath(entry.name);
    if (entry.uncompressedSize > MAX_FILE_BYTES) {
      throw new Error(`zip file too large: ${relPath}`);
    }

    // Decode first; the central directory's uncompressedSize is unreliable for
    // streaming/data-descriptor zips (it can read 0 even when the payload
    // carries real data). The inflate cap and the post-decode size checks below
    // are authoritative.
    const body = readEntryBody(zip, entry);
    if (body.length > MAX_FILE_BYTES) {
      throw new Error(`zip file too large: ${relPath}`);
    }
    if (entry.uncompressedSize > 0 && body.length !== entry.uncompressedSize) {
      throw new Error(`zip entry size mismatch: ${relPath}`);
    }
    totalBytes += body.length;
    if (totalBytes > MAX_TOTAL_BYTES) throw new Error('zip is too large');

    files.push({ path: relPath, body: normalizeImportedClaudeDesignFile(relPath, body) });
  }

View on GitHub (pinned to 5be4028344)

Solutions

  1. Remove or shrink the oversized entry so its declared uncompressed size is at or below 25 MiB.
  2. Externalize large media so it is not bundled in the zip.
  3. Re-export the design choosing only the HTML and minimal assets.
Defensive patterns

Strategy: validation

Validate before calling

const MAX_FILE_BYTES = 25 * 1024 * 1024;

function declaredSizesWithinCap(entries: { isDirectory: boolean; uncompressedSize: number }[]): boolean {
  return entries.filter((e) => !e.isDirectory).every((e) => e.uncompressedSize <= MAX_FILE_BYTES);
}

if (!declaredSizesWithinCap(entries)) {
  throw new Error('one or more entries declare an uncompressed size over 25 MiB');
}

Try / catch

try {
  await importClaudeDesignZip(zipPath, projectDir);
} catch (err) {
  if (err instanceof Error && /^zip file too large:/.test(err.message)) {
    // remove or shrink the named oversized entry
  }
  throw err;
}

Prevention

When it happens

Trigger: A zip entry whose central-directory header advertises an uncompressed size greater than 25 MiB (e.g. a large embedded media file, data file, or bundled script inside the Claude Design archive).

Common situations: An export that accidentally includes a large binary (video, image, database). A bundled JS file larger than 25 MiB. Note: for streaming/data-descriptor zips the declared size can read 0, in which case the post-decode check (error 234) is the one that trips.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/04b8b65bde8196bf. Report an issue: GitHub.