apache/incubator-seata · error · RuntimeException

Zip compress error

Error message

Zip compress error

What it means

Wrapped IOException from ZipUtil.compress thrown as RuntimeException('Zip compress error', e). Although compressing to an in-memory ByteArrayOutputStream rarely fails, ZipOutputStream can throw when the entry state is wrong — e.g. an entry with a preset size that mismatches the written bytes on close, or a nested entry error. The cause chain carries the real IOException.

Source

Thrown at compressor/seata-compressor-zip/src/main/java/org/apache/seata/compressor/zip/ZipUtil.java:47

 */
public class ZipUtil {

    private static final int BUFFER_SIZE = 8192;

    public static byte[] compress(byte[] bytes) {
        if (bytes == null) {
            throw new NullPointerException("bytes is null");
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (ZipOutputStream zip = new ZipOutputStream(out)) {
            ZipEntry entry = new ZipEntry("zip");
            entry.setSize(bytes.length);
            zip.putNextEntry(entry);
            zip.write(bytes);
            zip.closeEntry();
            return out.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException("Zip compress error", e);
        }
    }

    public static byte[] decompress(byte[] bytes) {
        if (bytes == null) {
            throw new NullPointerException("bytes is null");
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (ZipInputStream zip = new ZipInputStream(new ByteArrayInputStream(bytes))) {
            byte[] buffer = new byte[BUFFER_SIZE];
            while (zip.getNextEntry() != null) {
                int n;
                while ((n = zip.read(buffer)) > -1) {
                    out.write(buffer, 0, n);
                }
            }
            return out.toByteArray();
        } catch (IOException e) {

View on GitHub (pinned to e01f97c6db)

Solutions

  1. Read the cause exception: ZipException with 'incorrect number of bytes' / CRC means size metadata mismatched the data written.
  2. If you modified ZipUtil, remove the entry.setSize call or keep it exactly equal to bytes.length.
  3. Wrap the call and treat as non-retryable data error — do not loop retrying compression of the same bytes.
  4. Check for OOM in logs if payloads are huge; raise heap or switch to a streaming compressor.

Example fix

// before
ZipEntry entry = new ZipEntry("zip");
entry.setSize(bytes.length);

// after (size metadata optional; omit to let JDK compute it)
ZipEntry entry = new ZipEntry("zip");
Defensive patterns

Strategy: try-catch

Try / catch

try {
    byte[] zipped = ZipUtil.compress(bytes);
} catch (RuntimeException e) {
    // inspect e.getCause() for the underlying IOException; compression of in-memory bytes is non-retryable
    LOG.error("zip compress failed", e.getCause());
    throw e;
}

Prevention

When it happens

Trigger: entry.setSize(bytes.length) set to a wrong value so finish/close detects a size mismatch; calling compress concurrently on shared state (not the case here, it's per-call); JDK zip implementation errors such as 'ZIP file must have at least one entry' or CRC mismatches on close; extremely large payloads causing OutOfMemoryError-adjacent IO failures.

Common situations: Extending ZipUtil and mutating bytes.length vs actual write length; exotic JVMs or old JDK versions with stricter ZipOutputStream checks; corrupted heap producing inconsistent arrays (rare).

Related errors


AI-assisted analysis of apache/incubator-seata@e01f97c6db (2026-08-14). Data as JSON: /api/errors/d518df4ebda3d518. Report an issue: GitHub.