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

  1. Shorten or hash the entry name before putNextEntry (e.g. keep the extension, hash the prefix).
  2. If long names are inherent, truncate deterministically and keep a sidecar mapping of original name to entry name.
  3. 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

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


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