jstedfast/MailKit · error · InvalidOperationException
The Pop3Client is already connected.
Error message
The Pop3Client is already connected.
What it means
CheckCanConnect throws InvalidOperationException when Connect is called on a Pop3Client that already has an active connection (IsConnected is true). A Pop3Client instance manages exactly one POP3 session at a time, so connecting twice without disconnecting is refused. To connect elsewhere you must Disconnect (or dispose and create a new client) first.
Solutions
- Guard the call: only Connect when !client.IsConnected.
- Call Disconnect(quit: true, cancellationToken) before connecting to a new host/port.
- If a second concurrent session is needed, create a new Pop3Client instance instead of reusing the connected one.
- For reconnect-after-failure, check IsConnected and only reconnect when the previous session actually dropped.
Example fix
// before
client.Connect("pop.example.com", 995, SecureSocketOptions.SslOnConnect, ct);
// ... elsewhere
client.Connect("pop.other.com", 995, SecureSocketOptions.SslOnConnect, ct); // throws
// after
if (!client.IsConnected)
client.Connect("pop.other.com", 995, SecureSocketOptions.SslOnConnect, ct); Defensive patterns
Strategy: validation
Validate before calling
if (!client.IsConnected)
client.Connect(host, port, SecureSocketOptions.SslOnConnect, cancellationToken);
// else: reuse the existing session Try / catch
try {
client.Connect(host, port, SecureSocketOptions.SslOnConnect, ct);
} catch (InvalidOperationException) {
// already connected; reuse session or Disconnect first if a new target is required
} Prevention
- Guard every Connect call with an IsConnected check.
- Call Disconnect before connecting to a different host/port or with new settings.
- Use one Pop3Client instance per concurrent session; don't share a connected singleton across code paths that each connect.
- In reconnect logic, reconnect only when the previous session actually dropped.
When it happens
Trigger: Calling Connect() twice on the same Pop3Client instance without Disconnect(); a code path that re-connects on a timer/retry while the first session is still alive; reusing a singleton client for a different server while connected to the first.
Common situations: Auto-reconnect wrappers that forgot to check IsConnected; DI singleton Pop3Client shared across services that each call Connect; switching server/port settings at runtime without disconnecting first.
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
- No credentials could be found for the POP3 server.
- The POP3 server does not support the STLS extension.
- Capabilities cannot be enabled, they may only be disabled.
- The Pop3Client is not connected.
- The Pop3Client has not been authenticated.
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/7883b9de8d5d9bf4.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Net/Pop3/Pop3Client.cs:1101
break;
}
}
void CheckCanConnect (string host, int port)
{
if (host == null)
throw new ArgumentNullException (nameof (host));
if (host.Length == 0)
throw new ArgumentException ("The host name cannot be empty.", nameof (host));
if (port < 0 || port > 65535)
throw new ArgumentOutOfRangeException (nameof (port));
CheckDisposed ();
if (IsConnected)
throw new InvalidOperationException ("The Pop3Client is already connected.");
}
void SslHandshake (SslStream ssl, string host, CancellationToken cancellationToken)
{
#if NET5_0_OR_GREATER
ssl.AuthenticateAsClient (GetSslClientAuthenticationOptions (host, ValidateRemoteCertificate));
#else
ssl.AuthenticateAsClient (host, ClientCertificates, SslProtocols, CheckCertificateRevocation);
#endif
}
void PostConnect (Stream stream, string host, int port, SecureSocketOptions options, bool starttls, CancellationToken cancellationToken)
{
probed = ProbedCapabilities.None;
try {
ProtocolLogger.LogConnect (engine.Uri!);
} catch {View on GitHub (pinned to 9d3859a785)