{"record":{"id":"458c28061583ea9b","repo":"grpc/grpc-java","slug":"inflater-data-format-exception","errorCode":null,"errorMessage":"Inflater data format exception: ","messagePattern":"Inflater data format exception: ","errorType":"exception","errorClass":"DataFormatException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/grpc/internal/GzipInflatingBuffer.java","lineNumber":437,"sourceCode":"      int bytesConsumedDelta = inflater.getTotalIn() - inflaterTotalIn;\n      bytesConsumed += bytesConsumedDelta;\n      deflatedBytesConsumed += bytesConsumedDelta;\n      inflaterInputStart += bytesConsumedDelta;\n      crc.update(b, off, n);\n\n      if (inflater.finished()) {\n        // Save bytes written to check against the trailer ISIZE\n        expectedGzipTrailerIsize = (inflater.getBytesWritten() & 0xffffffffL);\n\n        state = State.TRAILER;\n      } else if (inflater.needsInput()) {\n        state = State.INFLATER_NEEDS_INPUT;\n      }\n\n      return n;\n    } catch (DataFormatException e) {\n      // Wrap the exception so tests can check for a specific prefix\n      throw new DataFormatException(\"Inflater data format exception: \" + e.getMessage());\n    }\n  }\n\n  private boolean fill() {\n    checkState(inflater != null, \"inflater is null\");\n    checkState(inflaterInputStart == inflaterInputEnd, \"inflaterInput has unconsumed bytes\");\n    int bytesToAdd = Math.min(gzippedData.readableBytes(), INFLATE_BUFFER_SIZE);\n    if (bytesToAdd == 0) {\n      return false;\n    }\n    inflaterInputStart = 0;\n    inflaterInputEnd = bytesToAdd;\n    gzippedData.readBytes(inflaterInput, inflaterInputStart, bytesToAdd);\n    inflater.setInput(inflaterInput, inflaterInputStart, bytesToAdd);\n    state = State.INFLATING;\n    return true;\n  }\n","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/core/src/main/java/io/grpc/internal/GzipInflatingBuffer.java#L419-L455","documentation":"When the java.util.zip.Inflater rejects the deflate stream, inflate() catches the raw DataFormatException and rethrows a new DataFormatException prefixed with 'Inflater data format exception: ' so callers/tests can match on the prefix. It means the compressed data itself (after the gzip header) violates the DEFLATE format.","triggerScenarios":"gzip header/trailer parse fine but the inflate() call on the body raises DataFormatException — e.g. non-deflate bytes between header and trailer, truncated deflate stream, or a stream produced with incompatible compression settings.","commonSituations":"Payload truncated by an idle-timeout or HTTP/2 flow-control bug; proxy stripping/replacing body bytes; wrong algorithm labeled as gzip (e.g. zstd, brotli); corrupted frames over flaky networks.","solutions":["Inspect the wrapped exception's message (getCause chain / prefix text) to identify the exact byte offset reported by the Inflater","Re-capture the payload and validate with `gzip -dc`; if it fails, fix the sender or intermediary corrupting the body","Ensure stream deadlines and flow control are not truncating large messages (tune maxInboundMessageSize, keepalive)","Confirm both peers use standard gzip (the only method gRPC's gzip encoding defines)"],"exampleFix":"// before\ntry {\n  stream.read(buffer);\n} catch (StatusRuntimeException e) {\n  // generic handling, data format detail lost\n}\n// after\ntry {\n  stream.read(buffer);\n} catch (StatusRuntimeException e) {\n  if (e.getCause() instanceof DataFormatException\n      && e.getCause().getMessage().startsWith(\"Inflater data format exception:\")) {\n    log.warn(\"Corrupt gzip body from peer\", e); // reconnect / re-request\n  } else {\n    throw e;\n  }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { call(...); } catch (StatusRuntimeException e) {\n  Throwable c = e.getCause();\n  if (c instanceof DataFormatException && c.getMessage().startsWith(\"Inflater data format exception:\")) {\n    log.error(\"corrupt gzip body: {}\", c.getMessage());\n    // re-request or fall back to identity compression\n  } else throw e;\n}","preventionTips":["Keep gRPC message-size limits and deadlines consistent so streams are not truncated mid-frame","Use TLS to protect body integrity","Match compression algorithms on both peers; only gzip is defined for the gzip encoding"],"tags":["grpc","gzip","deflate","data-corruption"],"backgroundTag":"invalid-json-response","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}