Tencent/tinker · error · IllegalArgumentException
${property} too long in UTF-8:${bytes.length} bytes
Error message
${property} too long in UTF-8:${bytes.length} bytes What it means
checkSizeIsWithinShort() enforces that an entry's name (or comment) does not exceed 65535 bytes when encoded as UTF-8, because the zip format stores these lengths as 16-bit fields. It throws IllegalArgumentException("<property> too long in UTF-8:<n> bytes") with property being "Entry Name" or similar, before the entry header is written.
Source
Thrown at third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/TinkerZipOutputStream.java:598
throw new IOException("Zip entry size (" + totalBytes +
" bytes) cannot be represented in the zip format (needs Zip64)." +
" Set the entry length using ZipEntry#setLength to use Zip64 where necessary.");
}*/
if (currentEntry.getMethod() == STORED) {
out.write(buffer, offset, byteCount);
} else {
out.write(buffer, offset, byteCount);
}
// crc.update(buffer, offset, byteCount);
}
private void checkOpen() throws IOException {
if (cDir == null) {
throw new IOException("Stream is closed");
}
}
private void checkSizeIsWithinShort(String property, byte[] bytes) {
if (bytes.length > 0xffff) {
throw new IllegalArgumentException(property
+ " too long in UTF-8:"
+ bytes.length
+ " bytes");
}
}
/*private long getBytesWritten() {
// This cast is somewhat messy but less error prone than keeping an
// CountingOutputStream reference around in addition to the FilterOutputStream's
// out.
return ((CountingOutputStream) out).getCount();
}*/
}
View on GitHub (pinned to 1b7ea02c23)
Solutions
- Shorten or hash the entry name before putNextEntry (e.g. keep the extension, hash the prefix).
- If long names are inherent, truncate deterministically and keep a sidecar mapping of original name to entry name.
- Validate nameBytes.length <= 0xffff in your own code and fail with a clear message identifying the offending entry.
Example fix
// before
String name = baseDir + "/" + veryLongGeneratedPath;
zos.putNextEntry(new TinkerZipEntry(name)); // IllegalArgumentException
// after
String name = baseDir + "/" + veryLongGeneratedPath;
if (name.getBytes(StandardCharsets.UTF_8).length > 0xffff) {
name = baseDir + "/" + sha1(veryLongGeneratedPath) + ".bin";
}
zos.putNextEntry(new TinkerZipEntry(name)); Defensive patterns
Strategy: validation
Validate before calling
static String safeEntryName(String name) {
if (name == null) return null;
byte[] b = name.getBytes(StandardCharsets.UTF_8);
return (b.length <= 0xffff) ? name : hashShorten(name); // deterministic fallback
}
// use: zos.putNextEntry(new TinkerZipEntry(safeEntryName(path))); Prevention
- Never use absolute filesystem paths as entry names
- Fuzz-test generated names against the 64 KiB limit
When it happens
Trigger: Calling putNextEntry() with an entry whose getName() encodes to more than 0xffff UTF-8 bytes (very deep paths or extremely long file names), or setting a comment longer than 64 KiB.
Common situations: Programmatically generated entry names (hash-based or concatenation-based) that grow unbounded; preserving absolute file-system paths as entry names; machine-generated comments; data migrated from formats without path-length limits.
Related errors
- No entries
- STORED entry missing CRC
- STORED entry missing size
- STORED entry size/compressed size mismatch
- No active entry
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/47dff8c9fbe34fdb.
Report an issue: GitHub.