{"record":{"id":"fefe8ad4f8ec38ee","repo":"Tencent/tinker","slug":"size-mismatch","errorCode":null,"errorMessage":"Size mismatch","messagePattern":"Size mismatch","errorType":"exception","errorClass":"ZipException","httpStatus":null,"severity":"error","filePath":"third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/AlignedZipOutputStream.java","lineNumber":158,"sourceCode":"     * @throws IOException\r\n     *             If an error occurs closing the entry.\r\n     */\r\n    public void closeEntry() throws IOException {\r\n        checkOpen();\r\n        if (currentEntry == null) {\r\n            return;\r\n        }\r\n        if (currentEntry.getMethod() == DEFLATED) {\r\n            super.finish();\r\n        }\r\n\r\n        // Verify values for STORED types\r\n        if (currentEntry.getMethod() == STORED) {\r\n            if (crc.getValue() != currentEntry.getCrc()) {\r\n                throw new ZipException(\"CRC mismatch\");\r\n            }\r\n            if (currentEntry.getSize() != crcDataSize) {\r\n                throw new ZipException(\"Size mismatch\");\r\n            }\r\n        }\r\n\r\n        int curOffset = LOCHDR;\r\n\r\n        // Write the DataDescriptor\r\n        if (currentEntry.getMethod() != STORED) {\r\n            curOffset += EXTHDR;\r\n            writeLong(out, EXTSIG);\r\n            currentEntry.setCrc(crc.getValue());\r\n            writeLong(out, currentEntry.getCrc());\r\n            currentEntry.setCompressedSize(def.getTotalOut());\r\n            writeLong(out, currentEntry.getCompressedSize());\r\n            currentEntry.setSize(def.getTotalIn());\r\n            writeLong(out, currentEntry.getSize());\r\n        }\r\n        // Update the CentralDirectory\r\n        // http://www.pkware.com/documents/casestudies/APPNOTE.TXT\r","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/AlignedZipOutputStream.java#L140-L176","documentation":"Companion to the CRC check: for STORED entries the stream tracks crcDataSize, the number of bytes actually written for the current entry, and closeEntry() requires currentEntry.getSize() to equal it. A mismatch means the declared size on the ZipEntry was wrong for the bytes written. Both checks exist because STORED entries carry their metadata up front in the local file header and cannot be patched after the fact without seeking.","triggerScenarios":"putNextEntry of a STORED entry whose setSize() disagrees with the byte count later passed to write() — e.g. size taken from a source zip entry but content filtered/modified, or an off-by-N in a partial-write loop.","commonSituations":"Repackaging APKs/zip archives with alignment (this class's purpose) while altering entry contents; copying entries with `entry.setSize(source.getSize())` but writing a different length; padding/alignment adjustments applied to the data but not reflected in size.","solutions":["Set size (and compressedSize) to the exact length of the byte array/stream you will write, and write exactly that many bytes — buffer content in memory (or temp file) first if needed.","Recompute all STORED metadata (size + CRC) from the final payload right before putNextEntry rather than reusing metadata from another archive.","If the content length is genuinely unknown, switch the entry to DEFLATED so the stream can emit a data descriptor."],"exampleFix":"// before: declared size copied from source, content re-encoded\nentry.setSize(srcEntry.getSize());\nzos.putNextEntry(entry);\nzos.write(newContent); // throws Size mismatch\n\n// after: declare size from the actual payload\nbyte[] newContent = encode(...);\nentry.setSize(newContent.length);\nentry.setCompressedSize(newContent.length);\nentry.setCrc(crcOf(newContent));\nzos.putNextEntry(entry);\nzos.write(newContent);","handlingStrategy":"validation","validationCode":"// Assert declared size equals the payload length before adding the entry\nif (entry.getMethod() == java.util.zip.ZipEntry.STORED && entry.getSize() != data.length) {\n    throw new IllegalStateException(\"declared size \" + entry.getSize()\n        + \" != payload length \" + data.length + \" for \" + entry.getName());\n}","typeGuard":null,"tryCatchPattern":"try {\n    zos.closeEntry();\n} catch (java.util.zip.ZipException e) {\n    if (\"Size mismatch\".equals(e.getMessage())) {\n        throw new IllegalStateException(\"STORED entry \" + entry.getName() + \" size disagrees with bytes written\", e);\n    }\n    throw e;\n}","preventionTips":["Derive size and compressedSize from the same byte array you will write — never mix sources.","Write STORED content in one call from a fully materialized buffer.","Unit-test archive round-trips (reopen and compare entry sizes) in your packaging build."],"tags":["zip","stored-entry","size","tinker"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}