Tencent/tinker · error · IllegalArgumentException

Bad CRC32: ${value}

Error message

Bad CRC32: ${value}

What it means

A zip entry's CRC32 is stored as an unsigned 32-bit value, so setCrc only accepts values in the range 0..0xFFFFFFFFL. Passing a negative long or any value above 0xFFFFFFFFL throws IllegalArgumentException. This mirrors the contract of java.util.zip.ZipEntry.setCrc. It usually means the caller computed or propagated a corrupted CRC value instead of reading one from CRC32.getValue().

Source

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

     * @return the checksum, or -1 if the checksum has not been set.
     */
    public long getCrc() {
        return crc;
    }

    /**
     * Sets the checksum for this {@code ZipEntry}.
     *
     * @param value
     *            the checksum for this entry.
     * @throws IllegalArgumentException
     *             if {@code value} is < 0 or > 0xFFFFFFFFL.
     */
    public void setCrc(long value) {
        if (value >= 0 && value <= 0xFFFFFFFFL) {
            crc = value;
        } else {
            throw new IllegalArgumentException("Bad CRC32: " + value);
        }
    }

    /**
     * Gets the extra information for this {@code ZipEntry}.
     *
     * @return a byte array containing the extra information, or {@code null} if
     *         there is none.
     */
    public byte[] getExtra() {
        return extra;
    }

    /**
     * Sets the extra information for this {@code ZipEntry}.
     *
     * @throws IllegalArgumentException if the data length >= 64 KiB.
     */

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Mask the value into unsigned 32-bit range before setting: setCrc(value & 0xFFFFFFFFL).
  2. Use java.util.zip.CRC32, call reset() then update()/getValue() so the result is always in range.
  3. Audit any int-to-long casts of CRC values in the call path and remove sign extension.

Example fix

// before
int crcFromHeader = ...; // may have high bit set
entry.setCrc(crcFromHeader); // implicit sign extension -> negative long

// after
entry.setCrc(crcFromHeader & 0xFFFFFFFFL);
Defensive patterns

Strategy: validation

Validate before calling

long crc = computeCrc(data);
if (crc < 0 || crc > 0xFFFFFFFFL) {
    throw new IllegalStateException("CRC computation bug: " + crc);
}
entry.setCrc(crc);

Prevention

When it happens

Trigger: Calling setCrc(value) where value < 0 or value > 0xFFFFFFFFL — typically a sign-extended int cast to long (e.g. setCrc((long) someInt) with the high bit set), or arithmetic that underflows/overflows when copying CRCs between entries.

Common situations: Porting code that stored CRCs in signed ints and reinterprets them with sign extension; recomputing a CRC with a buggy incremental update; copying metadata from a parsed zip header into a new entry.

Related errors


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