jstedfast/MailKit · error · IOException
Error inflating:
Error message
Error inflating:
What it means
Read() throws IOException("Error inflating: " + zIn.msg) when JZlib's inflate() returns a status other than Z_OK (and the special end-of-stream Z_BUF_ERROR case is excluded). zIn.msg carries zlib's description of the corrupted or unexpected compressed data.
Solutions
- Inspect zIn.msg / the IOException message to identify the zlib failure (data error, need dictionary, etc.).
- Verify the inner stream actually contains zlib data and was not corrupted or truncated; reconnect and reissue the COMPRESS command.
- Ensure you did not interleave raw writes/reads on the same socket outside CompressedStream, which desynchronizes the deflate/inflate state.
- Regenerate or re-fetch the compressed data; if the source data is bad, the stream cannot recover.
Example fix
// before
int n = compressedStream.Read(buffer, 0, buffer.Length); // IOException: Error inflating
// after
try {
int n = compressedStream.Read(buffer, 0, buffer.Length);
} catch (IOException ex) when (ex.Message.StartsWith("Error inflating")) {
// inner stream data is corrupt/not zlib - reconnect and restart COMPRESS
ReconnectAndRecompress();
} Defensive patterns
Strategy: try-catch
Validate before calling
// before reading, sanity-check the source is zlib data (RFC1950 header 0x78)
int first = innerStream.ReadByte();
if (first != 0x78) throw new InvalidDataException("Inner stream is not zlib-compressed.");
// (also keep a copy so the byte can be pushed back / stream recreated) Type guard
static bool IsZlibHeader(Stream s) {
int b = s.ReadByte();
if (b < 0) return false;
s.Position = s.CanSeek ? 0 : 0; // rewind only if seekable
return (b & 0x0F) == 8; // CMF: deflate method
} Try / catch
try {
int n = compressedStream.Read(buffer, 0, buffer.Length);
} catch (IOException ex) when (ex.Message.StartsWith("Error inflating")) {
// corrupt or non-zlib data: cannot recover inflate state; reconnect/restart session
logger.LogError(ex, "Inflate failure: {Msg}", ex.Message);
await ReconnectAsync();
} Prevention
- Verify COMPRESS (or zlib framing) is active before sending/receiving payload
- Never write raw/uncompressed bytes into a compressed session
- Handle network truncation promptly - treat partial frames as fatal to the stream
- Route ALL traffic through CompressedStream to avoid protocol desync
- Keep a reference to zlib msg details from the exception message when logging
When it happens
Trigger: Calling CompressedStream.Read when the underlying stream yields bytes that fail zlib inflation: corrupt/truncated compressed data, wrong compression window size, reading a stream not actually zlib-compressed, or protocol desync (e.g. an IMAP server response that is not compressed payload).
Common situations: IMAP COMPRESS sessions where the server sent a literal or untagged response that was not compressed, network truncation mid-stream, feeding a raw (uncompressed) stream into CompressedStream, zlib version/format mismatch.
Related errors
- Error deflating:
- The IMAP server does not support the COMPRESS extension.
- Compression must be enabled before selecting a folder.
- Value cannot be null. (Parameter 'name')
- Value cannot be null. (Parameter 'rights')
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/17238cc8fd1b7db5.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/CompressedStream.cs:213
do {
if (zIn.avail_in == 0 && !eos) {
zIn.avail_in = InnerStream.Read (zIn.next_in, 0, zIn.next_in.Length);
eos = zIn.avail_in == 0;
zIn.next_in_index = 0;
}
int retval = zIn.inflate (JZlib.Z_FULL_FLUSH);
if (retval == JZlib.Z_STREAM_END)
break;
if (eos && retval == JZlib.Z_BUF_ERROR)
return 0;
if (retval != JZlib.Z_OK)
throw new IOException ("Error inflating: " + zIn.msg);
} while (zIn.avail_out == count);
return count - zIn.avail_out;
}
/// <summary>
/// Reads a sequence of bytes from the stream and advances the position
/// within the stream by the number of bytes read.
/// </summary>
/// <returns>The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many
/// bytes are not currently available, or zero (0) if the end of the stream has been reached.</returns>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
/// <param name="count">The number of bytes to read.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <exception cref="System.ArgumentNullException">
/// <paramref name="buffer"/> is <see langword="null" />.
/// </exception>View on GitHub (pinned to 9d3859a785)