Tencent/tinker · error · ZipException
End Of Central Directory signature not found
Error message
End Of Central Directory signature not found
What it means
To find the End Of Central Directory record, readCentralDir scans backwards one byte at a time over at most the last 65536+ENDHDR bytes (the maximum zip comment length). If no ENDSIG ('PK\x05\x06') is found before hitting stopOffset, it throws ZipException('End Of Central Directory signature not found'). The usual cause is truncation: the EOCD lives at the very end of a zip, so a cut-off tail loses it.
Source
Thrown at third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/TinkerZipFile.java:444
final int headerMagic = Integer.reverseBytes(raf.readInt());
if (headerMagic != LOCSIG) {
throw new ZipException("Not a zip archive");
}
long stopOffset = scanOffset - 65536;
if (stopOffset < 0) {
stopOffset = 0;
}
while (true) {
raf.seek(scanOffset);
if (Integer.reverseBytes(raf.readInt()) == ENDSIG) {
break;
}
scanOffset--;
if (scanOffset < stopOffset) {
throw new ZipException("End Of Central Directory signature not found");
}
}
// Read the End Of Central Directory. ENDHDR includes the signature bytes,
// which we've already read.
byte[] eocd = new byte[ENDHDR - 4];
raf.readFully(eocd);
// Pull out the information we need.
BufferIterator it = HeapBufferIterator.iterator(eocd, 0, eocd.length, ByteOrder.LITTLE_ENDIAN);
int diskNumber = it.readShort() & 0xffff;
int diskWithCentralDir = it.readShort() & 0xffff;
int numEntries = it.readShort() & 0xffff;
int totalNumEntries = it.readShort() & 0xffff;
it.skip(4); // Ignore centralDirSize.
long centralDirOffset = ((long) it.readInt()) & 0xffffffffL;
int commentLength = it.readShort() & 0xffff;
View on GitHub (pinned to 1b7ea02c23)
Solutions
- Verify the file size against the expected total (Content-Length, checksum) and re-download if it is short.
- If you have the original, compare sizes to confirm truncation; if only the comment area is damaged, strip the trailing bytes and attempt recovery with 'zip -FF'.
- For files you generate, ensure nothing is appended after the zip comment; keep comments < 64 KiB.
Example fix
// before
TinkerZipFile zf = new TinkerZipFile(new File(patchPath)); // truncated download
// after
long expected = downloader.expectedSize(patchUrl);
File f = new File(patchPath);
if (f.length() != expected) {
downloader.refetch(patchUrl, f);
}
TinkerZipFile zf = new TinkerZipFile(f); Defensive patterns
Strategy: validation
Validate before calling
// cheapest reliable guard: compare against expected total size / checksum
if (expectedBytes != null && file.length() != expectedBytes) {
throw new IOException("Truncated archive: " + file.length() + " of " + expectedBytes + " bytes");
}
TinkerZipFile zf = new TinkerZipFile(file); Try / catch
try {
zf = new TinkerZipFile(file);
} catch (ZipException e) {
if (e.getMessage().contains("End Of Central Directory signature not found")) {
throw new IOException("Archive truncated or damaged (no EOCD): re-download " + file, e);
}
throw e;
} Prevention
- Always checksum/size-verify downloads of zip artifacts before processing.
- Do not append data after a zip's comment when generating archives.
- Watch for filesystem file-size ceilings (e.g. 4 GiB on FAT32) when moving large zips.
When it happens
Trigger: Opening a zip whose final <=64 KiB contains no EOCD signature — truncated downloads (missing final bytes), files truncated to a fixed size (FAT 4 GiB limit, transfer cap), or a central directory larger than the scan window combined with a comment-sized gap.
Common situations: Interrupted downloads of large APK/patch files; copying a zip onto a filesystem with a smaller file-size ceiling; some binary-patching tools appending data after the comment so the EOCD moves outside the scanned window.
Related errors
- File too short to be a zip file: ${raf.length()}
- Expected ${DEX_IN_JAR_NAME} in ${file}
- Map is unsorted at ${section}
- CRC mismatch
- Size mismatch
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/50ff2b6fa75822c3.
Report an issue: GitHub.