Tencent/tinker · error · IllegalArgumentException

Bad size: ${value}

Error message

Bad size: ${value}

What it means

setSize sets the uncompressed size of an entry, which the zip format stores as a non-negative quantity. A negative value throws IllegalArgumentException('Bad size'). Note this library's guard is only value < 0 — unlike the Harmony/Android original it does not enforce the 32-bit zip1 limit here, but a negative size always indicates uninitialized or corrupted state in the caller (e.g. -1 'unknown' sentinel).

Source

Thrown at third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/TinkerZipEntry.java:351

    /**
     * Gets the uncompressed size of this {@code ZipEntry}.
     *
     * @return the uncompressed size, or {@code -1} if the size has not been
     *         set.
     */
    public long getSize() {
        return size;
    }

    /**
     * Sets the uncompressed size of this {@code ZipEntry}.
     *
     * @param value the uncompressed size for this entry.
     * @throws IllegalArgumentException if {@code value < 0}.
     */
    public void setSize(long value) {
        if (value < 0) {
            throw new IllegalArgumentException("Bad size: " + value);
        }
        size = value;
    }

    /**
     * Gets the last modification time of this {@code ZipEntry}.
     *
     * @return the last modification time as the number of milliseconds since
     *         Jan. 1, 1970.
     */
    public long getTime() {
        if (time != -1) {
            GregorianCalendar cal = new GregorianCalendar();
            cal.set(Calendar.MILLISECOND, 0);
            cal.set(1980 + ((modDate >> 9) & 0x7f), ((modDate >> 5) & 0xf) - 1,
                    modDate & 0x1f, (time >> 11) & 0x1f, (time >> 5) & 0x3f,
                    (time & 0x1f) << 1);
            return cal.getTime().getTime();

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Only call setSize when you have a real non-negative size; skip the call entirely if the source reports -1 (unknown).
  2. Compute sizes from the actual data (e.g. after reading the stream) rather than propagating sentinels.
  3. Check for -1 explicitly and throw your own descriptive error upstream, so the failure is not buried in the zip writer.

Example fix

// before
long srcSize = sourceEntry.getSize(); // -1 when unset
newEntry.setSize(srcSize);

// after
long srcSize = sourceEntry.getSize();
if (srcSize >= 0) {
    newEntry.setSize(srcSize);
}
Defensive patterns

Strategy: validation

Validate before calling

long sz = sourceEntry.getSize();
if (sz >= 0) {
    newEntry.setSize(sz);
}
// skip the call when sz == -1 (unknown)

Prevention

When it happens

Trigger: Calling setSize(value) with value < 0, most commonly forwarding -1 from an API that uses -1 to mean 'size unknown' (java.util.zip.ZipEntry.getSize returns -1 when unset), or a subtraction that underflowed.

Common situations: Reading sizes from a parsed central directory where the field failed to parse; copying from a source entry whose size was never set; using -1 as a placeholder before the real size is known.

Related errors


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