apache/incubator-seata · error · RuntimeException

gzip decompress error

Error message

gzip decompress error

What it means

Wrapped IOException thrown by GzipUtil.decompress as RuntimeException("gzip decompress error", e). It fires when GZIPInputStream cannot read the payload: the data is not in gzip format (bad magic bytes), the stream is truncated/corrupted, or the CRC/checksum fails on finish. The original IOException is attached as the cause for diagnosis.

Source

Thrown at compressor/seata-compressor-gzip/src/main/java/org/apache/seata/compressor/gzip/GzipUtil.java:60

            throw new RuntimeException("gzip compress error", e);
        }
    }

    public static byte[] decompress(byte[] bytes) {
        if (bytes == null) {
            throw new NullPointerException("bytes is null");
        }

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (GZIPInputStream gunzip = new GZIPInputStream(new ByteArrayInputStream(bytes))) {
            byte[] buffer = new byte[BUFFER_SIZE];
            int n;
            while ((n = gunzip.read(buffer)) > -1) {
                out.write(buffer, 0, n);
            }
            return out.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException("gzip decompress error", e);
        }
    }
}

View on GitHub (pinned to e01f97c6db)

Solutions

  1. Inspect the cause in the stack trace — 'Not in GZIP format' means wrong data, 'Unexpected end of ZLIB input stream' means truncation.
  2. Verify the compressor id/type configured on both ends of the RPC matches (registry and compressor config).
  3. If data comes from storage, re-read or regenerate it (e.g. clear the poisoned undo_log rows) rather than retrying decompression.
  4. Sanity-check the first two bytes are 0x1f 0x8b before calling decompress.

Example fix

// before
byte[] out = GzipUtil.decompress(bytes);

// after
if (bytes.length < 2 || (bytes[0] & 0xff) != 0x1f || (bytes[1] & 0xff) != 0x8b) {
    throw new IllegalArgumentException("payload is not gzip (bad magic bytes)");
}
byte[] out = GzipUtil.decompress(bytes);
Defensive patterns

Strategy: try-catch

Validate before calling

boolean isGzip(byte[] b) {
    return b != null && b.length >= 2 && (b[0] & 0xff) == 0x1f && (b[1] & 0xff) == 0x8b;
}

Try / catch

try {
    byte[] out = GzipUtil.decompress(bytes);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("gzip decompress error")) {
        // treat as corrupt/foreign payload: log cause, reject message, do not retry
    } else { throw e; }
}

Prevention

When it happens

Trigger: Passing bytes that were not gzip-compressed (raw, zip, or lz4 payloads); a truncated byte array (partial network read, wrong length prefix); corrupted rollback-info stored in a database table; calling decompress on an empty non-null array (new byte[0]) which makes the GZIPInputStream constructor throw ZipException 'Not in GZIP format'.

Common situations: Compressor type mismatch between seata client and server (client compresses with zstd, server decompresses with gzip); corrupted undo_log/branch session data after a DB character-set incident; a proxy or middleware mangling binary bodies; version upgrade changing the default compressor.

Related errors


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