jstedfast/MailKit · error · InvalidOperationException
Compression must be enabled before selecting a folder.
Error message
Compression must be enabled before selecting a folder.
What it means
IMAP compression changes the connection's encoding, so it must be negotiated while the session is still unselected (before any folder is open). QueueCompressCommand throws InvalidOperationException if engine.State is Selected or beyond, because compressing mid-selection would corrupt the stream state.
Solutions
- Call Compress() immediately after Connect/Authenticate and before opening any folder
- Reorder your setup: Connect -> Authenticate -> Compress -> OpenFolder
- If compression is needed later, disconnect, reconnect, compress, then select
Example fix
// before
await client.ConnectAsync(...);
await client.AuthenticateAsync(...);
var folder = await client.GetFolderAsync("INBOX");
await folder.OpenAsync(FolderAccess.ReadWrite);
client.Compress(); // throws - folder already selected
// after
await client.ConnectAsync(...);
await client.AuthenticateAsync(...);
client.Compress();
var folder = await client.GetFolderAsync("INBOX");
await folder.OpenAsync(FolderAccess.ReadWrite); Defensive patterns
Strategy: validation
Validate before calling
if (client is ImapClient imap && imap.State == ImapEngineState.Selected)
throw new InvalidOperationException("Call Compress before opening a folder."); Try / catch
try {
client.Compress();
} catch (InvalidOperationException) {
// reconnect and compress before selecting, or skip compression
} Prevention
- Fixed setup order: Connect -> Authenticate -> Compress -> OpenFolder
- Never call Compress mid-session after folders were opened
- Centralize connection setup in one helper so ordering is guaranteed
When it happens
Trigger: Calling client.Compress() after a folder has already been selected/opened (e.g. after GetFolder(...).Open(...)) on the same connection.
Common situations: Adding compression to an existing code path after mailbox operations; enabling compression in the middle of a long-lived session that already opened INBOX; copy-pasting Compress() after folder-opening boilerplate.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Error inflating:
- The IMAP server does not support the COMPRESS extension.
- Untagged handlers must be registered before the command has…
- 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/444a79d513d7d2c4.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Net/Imap/ImapClient.cs:295
if (!valid) {
// Note: The SslHandshakeException.Create() method will nullify this once it's done using it.
sslValidationInfo = new SslCertificateValidationInfo (host, certificate, chain, sslPolicyErrors);
}
return valid;
}
ImapCommand QueueCompressCommand (CancellationToken cancellationToken)
{
CheckDisposed ();
CheckConnected ();
if ((engine.Capabilities & ImapCapabilities.Compress) == 0)
throw new NotSupportedException ("The IMAP server does not support the COMPRESS extension.");
if (engine.State >= ImapEngineState.Selected)
throw new InvalidOperationException ("Compression must be enabled before selecting a folder.");
#if MAILKIT_LITE
throw new NotSupportedException ("MailKitLite does not support the COMPRESS extension.");
#else
return engine.QueueCommand (cancellationToken, null, "COMPRESS DEFLATE\r\n");
#endif
}
void ProcessCompressResponse (ImapCommand ic)
{
#if !MAILKIT_LITE
if (ic.Response != ImapCommandResponse.Ok) {
for (int i = 0; i < ic.RespCodes.Count; i++) {
if (ic.RespCodes[i].Type == ImapResponseCodeType.CompressionActive)
return;
}
throw ImapCommandException.Create ("COMPRESS", ic);View on GitHub (pinned to 9d3859a785)