jstedfast/MailKit · critical · ImapProtocolException
The IMAP server has unexpectedly disconnected.
Error message
The IMAP server has unexpectedly disconnected.
What it means
MailKit throws this ImapProtocolException from ImapStream.ReadAhead when reading from the socket returns 0 bytes or otherwise fails mid-command, meaning the TCP connection to the IMAP server dropped without a proper BYE response. Setting IsConnected=false, the ImapClient transitions to a disconnected state and the in-flight command fails.
Solutions
- Reconnect: create/reconnect the ImapClient, re-authenticate, and re-select the folder, then retry the operation
- Wrap long-running sessions with periodic NOOP keepalive (ImapClient's KeepAlive) to defeat idle timeouts
- Implement retry logic that detects ImapProtocolException/ServiceNotConnected and rebuilds the connection
- Check server logs and network path (NAT idle timeout, LB settings) if drops are frequent
Example fix
// before
var messages = folder.Fetch (0, -1, summary);
// after
try {
var messages = folder.Fetch (0, -1, summary);
} catch (ImapProtocolException) {
client.Disconnect (true);
client.Connect (host, port, useSsl);
client.Authenticate (user, pass);
folder = client.GetFolder (folderName);
folder.Open (FolderAccess.ReadOnly);
var messages = folder.Fetch (0, -1, summary);
} Defensive patterns
Strategy: retry
Validate before calling
if (!client.IsConnected) { await ReconnectAsync (); } Try / catch
try { return await folder.FetchAsync (0, -1, summary); } catch (ImapProtocolException ex) { await ReconnectAsync (); return await folder.FetchAsync (0, -1, summary); } Prevention
- Enable keepalive NOOPs
- Retry with reconnect on ImapProtocolException
- Keep operations idempotent
When it happens
Trigger: Server process crash/restart, idle connection killed by a NAT/firewall/load balancer, network outage, or server closing the connection during any read (ReadLine, token parsing, literal reads).
Common situations: Long-lived connections with NOOP keepalives disabled hitting idle timeouts; server maintenance windows; flaky mobile/VPN networks; reading a large message fetch when the server dies mid-literal.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- The ImapClient is not connected.
- Value cannot be null. (Parameter 'name')
- Value cannot be null. (Parameter 'rights')
- Value cannot be null. (Parameter 'array')
- Specified argument was out of range of valid values…
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/69c43d94006adbe6.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Net/Imap/ImapStream.cs:321
int ReadAhead (int atleast, CancellationToken cancellationToken)
{
if (!AlignReadAheadBuffer (atleast, out int left, out int start, out int end))
return left;
try {
var network = Stream as NetworkStream;
int nread;
cancellationToken.ThrowIfCancellationRequested ();
network?.Poll (SelectMode.SelectRead, cancellationToken);
if ((nread = Stream.Read (input, start, end - start)) > 0) {
logger.LogServer (input, start, nread);
inputEnd += nread;
} else {
throw new ImapProtocolException ("The IMAP server has unexpectedly disconnected.");
}
if (network == null)
cancellationToken.ThrowIfCancellationRequested ();
} catch {
IsConnected = false;
throw;
}
return inputEnd - inputIndex;
}
async ValueTask<int> ReadAheadAsync (int atleast, CancellationToken cancellationToken)
{
if (!AlignReadAheadBuffer (atleast, out int left, out int start, out int end))
return left;
try {View on GitHub (pinned to 9d3859a785)