Tencent/tinker · error · ZipException

Too many entries for the zip file format's 16-bit entry coun

Error message

Too many entries for the zip file format's 16-bit entry count

What it means

The zip format's central directory records the entry count in a 16-bit field, capping a classic zip at 65,535 entries. This stream does not implement Zip64, so once the running entries set reaches 64*1024-1 the next putNextEntry is refused. The check happens before any bytes are written for the new entry, keeping the archive consistent.

Source

Thrown at third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/AlignedZipOutputStream.java:331

            }
            if (ze.getCrc() == -1) {
                throw new ZipException("STORED entry missing CRC");
            }
            if (ze.getSize() == -1) {
                throw new ZipException("STORED entry missing size");
            }
            if (ze.getSize() != ze.getCompressedSize()) {
                throw new ZipException("STORED entry size/compressed size mismatch");
            }
        }

        checkOpen();

        if (entries.contains(ze.getName())) {
            throw new ZipException("Entry already exists: " + ze.getName());
        }
        if (entries.size() == 64*1024-1) {
            throw new ZipException("Too many entries for the zip file format's 16-bit entry count");
        }
        nameBytes = ze.getName().getBytes(Charset.forName("UTF-8"));
        nameLength = nameBytes.length;
        if (nameLength > 0xffff) {
            throw new IllegalArgumentException("Name too long: " + nameLength + " UTF-8 bytes");
        }

        def.setLevel(compressionLevel);
        ze.setMethod(method);

        currentEntry = ze;
        entries.add(currentEntry.getName());

        // Local file header.
        // http://www.pkware.com/documents/casestudies/APPNOTE.TXT
        int flags = (method == STORED) ? 0 : GPBF_DATA_DESCRIPTOR_FLAG;
        // Java always outputs UTF-8 filenames. (Before Java 7, the RI didn't set this flag and used
        // modified UTF-8. From Java 7, it sets this flag and uses normal UTF-8.)

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Count entries before writing: if the planned set exceeds 65,535, prune redundant files (unused resources, duplicate metadata) until under the limit.
  2. Split the output into multiple archives (e.g. assets split, expansion files, multidex-style sharding) so each stays under 65,535 entries.
  3. If a single huge archive is a hard requirement, use a Zip64-capable writer for that artifact instead of this class, then verify consumers can read Zip64.

Example fix

// before: unconditional add in a loop
for (File f : files) {
    zos.putNextEntry(new ZipEntry(prefix + f.getName())); // throws at 65535th
}

// after: pre-validate the entry budget
if (files.size() > 64 * 1024 - 1) {
    throw new IllegalStateException("too many zip entries; split the archive");
}
for (File f : files) {
    zos.putNextEntry(new ZipEntry(prefix + f.getName()));
}
Defensive patterns

Strategy: validation

Validate before calling

// Check the entry budget up front
static final int MAX_ZIP_ENTRIES = 64 * 1024 - 1;
if (plannedEntryNames.size() > MAX_ZIP_ENTRIES) {
    throw new IllegalStateException("archive would exceed the 65535-entry zip limit; split or prune");
}

Try / catch

try {
    zos.putNextEntry(entry);
} catch (java.util.zip.ZipException e) {
    if (e.getMessage() != null && e.getMessage().contains("16-bit entry count")) {
        // finish the current archive, roll over to a new part
        zos.close();
        zos = openNewPart();
        zos.putNextEntry(entry);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Writing an archive with more than 65,535 entries — e.g. packaging a project with tens of thousands of resource/asset files, or accidentally adding generated/duplicated files in a loop until the limit is hit.

Common situations: Large apps whose res/ + assets/ + generated code push past 64K files; a build step that accidentally emits per-class or per-locale files without dedupe; using this non-Zip64 writer where the input archive is already near the limit (Android's AAPT-era limit is a known relative of this one).

Related errors


AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14). Data as JSON: /api/errors/6f2b362a57c2e564. Report an issue: GitHub.