jstedfast/MailKit · error · ServiceNotConnectedException

The Pop3Client is not connected.

Error message

The Pop3Client is not connected.

What it means

Pop3Client.CheckConnected is the guard invoked before nearly every network operation (GetMessageCount, Size, NoOp, language commands, etc.); it throws ServiceNotConnectedException when IsConnected is false. It means the client has never connected, or the connection was dropped/closed before the call.

Solutions

  1. Check client.IsConnected before operations and call ConnectAsync/AuthenticateAsync when false.
  2. Wrap operations in a reconnect helper: catch ServiceNotConnectedException, reconnect, retry once.
  3. Don't reuse stale client instances across long gaps; create and connect a fresh Pop3Client per unit of work (POP3 sessions are short-lived by design).

Example fix

// before
using var client = new Pop3Client();
await client.ConnectAsync(host, 995, true);
// ... later, connection dropped ...
int count = await client.GetMessageCountAsync(); // throws

// after
using var client = new Pop3Client();
async Task EnsureConnectedAsync()
{
    if (!client.IsConnected)
    {
        await client.ConnectAsync(host, 995, true);
        await client.AuthenticateAsync(user, pass);
    }
}
await EnsureConnectedAsync();
int count = await client.GetMessageCountAsync();
Defensive patterns

Strategy: try-catch

Validate before calling

if (client == null || !client.IsConnected)
    throw new InvalidOperationException("Pop3Client must be connected before use");

Try / catch

try { await client.GetMessageCountAsync(); }
catch (ServiceNotConnectedException) {
    await client.ConnectAsync(host, 995, true);
    await client.AuthenticateAsync(user, pass);
    await client.GetMessageCountAsync();
}

Prevention

When it happens

Trigger: Calling any Pop3Client operation before ConnectAsync, after DisconnectAsync, after a timeout/protocol exception disconnected the client, or after the server dropped the connection.

Common situations: Reusing a client instance across a previous failed session; forgetting Connect in a code path; a prior TimeoutException/ImapProtocolException-style disconnect left the client dead and subsequent calls fail; wrong assumption that a client stays connected between application requests.

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


AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15). Data as JSON: /api/errors/8639d1394d54bb68. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/Net/Pop3/Pop3Client.cs:250

			get {
				CheckDisposed ();
				CheckConnected ();
				CheckAuthenticated ();

				return octets;
			}
		}

		void CheckDisposed ()
		{
			if (disposed)
				throw new ObjectDisposedException (nameof (Pop3Client));
		}

		void CheckConnected ()
		{
			if (!IsConnected)
				throw new ServiceNotConnectedException ("The Pop3Client is not connected.");
		}

		void CheckAuthenticated ()
		{
			if (!IsAuthenticated)
				throw new ServiceNotAuthenticatedException ("The Pop3Client has not been authenticated.");
		}

		bool ValidateRemoteCertificate (object? sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors)
		{
			var host = engine.Uri!.Host;
			bool valid;

			sslValidationInfo?.Dispose ();
			sslValidationInfo = null;

			if (ServerCertificateValidationCallback != null) {
				valid = ServerCertificateValidationCallback (host, certificate, chain, sslPolicyErrors);

View on GitHub (pinned to 9d3859a785)