Tencent/tinker · error · ZipException
STORED entry missing size
Error message
STORED entry missing size
What it means
For STORED entries the uncompressed and compressed sizes must be known before data is written. putNextEntry() first tries to derive one from the other (if compressedSize == -1 it copies size, and vice versa); if BOTH size and compressedSize are still -1 it throws ZipException("STORED entry missing size"). Unlike DEFLATED, STORED data is written verbatim so sizes cannot be discovered while streaming.
Source
Thrown at third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/TinkerZipOutputStream.java:464
closeEntry();
}
// Did this ZipEntry specify a method, or should we use the default?
int method = ze.getMethod();
if (method == -1) {
method = defaultCompressionMethod;
}
// If the method is STORED, check that the ZipEntry was configured appropriately.
if (method == STORED) {
if (ze.getCompressedSize() == -1) {
ze.setCompressedSize(ze.getSize());
} else if (ze.getSize() == -1) {
ze.setSize(ze.getCompressedSize());
}
if (ze.getCrc() == -1) {
throw new ZipException("STORED entry missing CRC");
}
if (ze.getSize() == -1) {
throw new ZipException("STORED entry missing size");
}
if (ze.size != ze.compressedSize) {
throw new ZipException("STORED entry size/compressed size mismatch");
}
}
checkOpen();
// checkAndSetZip64Requirements(ze);
//zhangshaowen edit here, we just want the same time and modDate
ze.comment = null;
ze.extra = null;
ze.time = TIME_CONST;
ze.modDate = MOD_DATE_CONST;
nameBytes = ze.name.getBytes(StandardCharsets.UTF_8);
checkSizeIsWithinShort("Name", nameBytes);
entryCommentBytes = BYTE;
if (ze.comment != null) {View on GitHub (pinned to 1b7ea02c23)
Solutions
- Buffer the entry data (byte[] or temp file) so its length is known, then call ze.setSize(len) and ze.setCompressedSize(len) before putNextEntry().
- If the data is copied from another zip entry, copy the source entry's size and compressedSize fields across along with crc.
- Switch the entry to DEFLATED if the length genuinely cannot be known up front.
Example fix
// before
TinkerZipEntry e = new TinkerZipEntry("assets/blob.bin");
e.setMethod(TinkerZipEntry.STORED);
e.setCrc(crc32);
zos.putNextEntry(e); // throws: missing size
// after
TinkerZipEntry e = new TinkerZipEntry("assets/blob.bin");
e.setMethod(TinkerZipEntry.STORED);
e.setCrc(crc32);
e.setSize(dataLen);
e.setCompressedSize(dataLen);
zos.putNextEntry(e); Defensive patterns
Strategy: validation
Validate before calling
void putStored(TinkerZipOutputStream zos, String name, byte[] data) throws IOException {
CRC32 crc = new CRC32();
crc.update(data);
TinkerZipEntry e = new TinkerZipEntry(name);
e.setMethod(TinkerZipEntry.STORED);
e.setCrc(crc.getValue());
e.setSize(data.length);
e.setCompressedSize(data.length);
zos.putNextEntry(e);
zos.write(data, 0, data.length);
zos.closeEntry();
} Prevention
- Buffer unknown-length data (memory or temp file) before writing STORED entries
- Set size and compressedSize from the same length variable
When it happens
Trigger: putNextEntry(entry) with method STORED where neither entry.setSize(...) nor entry.setCompressedSize(...) was ever called — both remain at their -1 default after the derivation block runs.
Common situations: Streaming a dynamically generated file (unknown length) into a STORED entry; converting a DEFLATED pipeline to STORED and only setting the CRC but not sizes; copying entries from a source zip whose size fields were not read/populated.
Related errors
- Size mismatch
- STORED entry missing CRC
- STORED entry size/compressed size mismatch
- CRC mismatch
- Bad size: ${value}
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/f803db11d6b5dddc.
Report an issue: GitHub.