can1357/oh-my-pi · error · ArchiveError
ZIP archive is too large to write
Error message
ZIP archive is too large to write
What it means
Final sanity check in the ZIP writer: the accumulated local-data size plus central-directory size must stay a safe integer, and the member count must not exceed U32_MAX. Exceeding these means the archive bookkeeping can no longer be represented correctly, so the writer aborts.
Source
Thrown at packages/utils/src/ar/zip.ts:674
writeUInt16LE(central, 4, (UNIX_HOST << 8) | 20);
writeUInt16LE(central, 6, 20);
writeUInt16LE(central, 8, UTF8_FLAG);
writeUInt16LE(central, 10, method);
writeUInt16LE(central, 12, 0);
writeUInt16LE(central, 14, 0x21);
writeUInt32LE(central, 16, checksum);
writeUInt32LE(central, 20, payload.byteLength);
writeUInt32LE(central, 24, data.byteLength);
writeUInt16LE(central, 28, nameBytes.byteLength);
writeUInt32LE(central, 38, (0o100644 << 16) >>> 0);
writeUInt32LE(central, 42, localSize);
central.set(nameBytes, 46);
centralParts.push(central);
localSize += local.byteLength + payload.byteLength;
centralSize += central.byteLength;
count++;
if (!Number.isSafeInteger(localSize + centralSize) || count > U32_MAX) {
throw new ArchiveError("ZIP archive is too large to write");
}
}
if (localSize >= U32_MAX || centralSize >= U32_MAX) {
throw new ArchiveError("ZIP archive is too large to write member offsets safely");
}
const zip64 = count >= U16_MAX;
const trailerLength = EOCD_LENGTH + (zip64 ? ZIP64_EOCD_LENGTH + ZIP64_LOCATOR_LENGTH : 0);
const totalSize = localSize + centralSize + trailerLength;
if (!Number.isSafeInteger(totalSize)) throw new ArchiveError("ZIP archive is too large to write");
const output = new Uint8Array(totalSize);
let outputOffset = 0;
for (const part of localParts) {
output.set(part, outputOffset);
outputOffset += part.byteLength;
}
for (const part of centralParts) {
output.set(part, outputOffset);
outputOffset += part.byteLength;View on GitHub (pinned to 9690622007)
Solutions
- Split the members across multiple ZIP archives (batch writes, e.g. 10k-100k members per archive)
- Deduplicate or exclude generated files before archiving (respect ignore lists)
- Check member count and total size before calling the writer and shard accordingly
- Use a streaming archiver designed for very large entry counts
Example fix
// before: single zip of every file
await writeZip(millionsOfMembers);
// after: batch
for (let i = 0; i < millionsOfMembers.length; i += 50000)
await writeZip(millionsOfMembers.slice(i, i + 50000).map((m, j) => ({ ...m, name: `part${i / 50000}/${m.name}` }))); Defensive patterns
Strategy: validation
Validate before calling
function assertZipBookkeepingSafe(members: { name: string; data: Uint8Array }[]): void {
const count = members.length;
const total = members.reduce((s, m) => s + 30 + Buffer.byteLength(m.name, 'utf8') + m.data.byteLength, 0) + count * 46;
if (!Number.isSafeInteger(total) || count > 0xffffffff)
throw new Error(`zip too large: ${count} entries, ${total} bytes`);
} Try / catch
try {
await writeZip(members);
} catch (err) {
if (err instanceof ArchiveError && err.message === 'ZIP archive is too large to write') {
logger.error('zip bookkeeping overflow', { entryCount: members.length });
return batchWriteZips(members, 50000);
}
throw err;
} Prevention
- Cap member count per archive with batching
- Exclude vendored/generated file floods via ignore lists
- Sum member sizes before writing to catch overflow early
When it happens
Trigger: Calling the zip write API with an enormous number of members (> 4,294,967,295 entries) or sizes whose running total overflows Number.isSafeInteger (>= 2^53 bytes) — practically, extremely large in-memory archive builds.
Common situations: Archiving millions of tiny files (e.g. node_modules, extracted datasets) into one zip in memory; runaway code adding members in a loop without a bound; accumulator bugs in generated member lists.
Related errors
- ${name} exceeds the ${SHARPSHOOTER_MAX_FILE_LINES}-line limi
- Archive is too large to read in memory (${formatBytes(size)}
- ZIP member path '${name}' is too long to write
- Managed skill is ${bytes} bytes; the limit is ${MAX_MANAGED_
- Summary exceeds ${config.summaryHardLimit} bytes
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/a105af9cdf4cbfa3.
Report an issue: GitHub.