jstedfast/MailKit · error · InvalidOperationException

QRESYNC needs to be enabled immediately after…

Error message

QRESYNC needs to be enabled immediately after authenticating.

What it means

MailKit requires the QRESYNC (RFC 7162) extension to be enabled in the small window right after authentication, before any folder is selected. ImapClient.EnableQuickResync queues the ENABLE QRESYNC command, and this InvalidOperationException is thrown when the engine state is no longer ImapEngineState.Authenticated (e.g. a folder is already selected or the connection moved on). The library enforces this because the IMAP ENABLE command is only valid pre-authentication-completion of other state changes.

Solutions

  1. Call EnableQuickResync immediately after Authenticate and before any folder is selected or any other command is issued
  2. If a folder is already open, disconnect and reconnect, re-authenticate, then enable QRESYNC first
  3. Verify engine.State with client.Capabilities/state logging; ensure no background task issues commands before enabling
  4. Cache the fact that QRESYNC was enabled (engine.QResyncEnabled) to avoid re-calling on the same connection

Example fix

// before
client.Authenticate (user, pass);
var folder = client.GetFolder ("INBOX");
folder.Open (FolderAccess.ReadWrite);
client.EnableQuickResync (); // throws: state != Authenticated
// after
client.Authenticate (user, pass);
client.EnableQuickResync ();
var folder = client.GetFolder ("INBOX");
folder.Open (FolderAccess.ReadWrite);
Defensive patterns

Strategy: validation

Validate before calling

if (client.IsAuthenticated && !client.IsDisposed && noFolderOpened(client)) client.EnableQuickResync ();

Type guard

bool CanEnableQresync (ImapClient c) => c.IsConnected && c.IsAuthenticated && (c.Capabilities & ImapCapabilities.QuickResync) != 0;

Try / catch

try { client.EnableQuickResync (); } catch (InvalidOperationException ex) { /* session already advanced past Authenticated; reconnect or skip */ } catch (NotSupportedException) { /* server lacks QRESYNC */ }

Prevention

When it happens

Trigger: Calling EnableQuickResync() (or EnableQuickResyncAsync) after the engine state has advanced past Authenticated — typically after SelectFolder/Folder opened, or after other commands were issued; also if a reconnection or idle resumption changed engine.State.

Common situations: Calling EnableQuickResync after client.GetFolder(...).Open(...) or after Fetch; enabling QRESYNC on a cached/reconnected ImapClient whose state was restored; calling it in a retry loop after it partially progressed.

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/56696e51fe10982d. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/Net/Imap/ImapClient.cs:370

		/// An IMAP protocol error occurred.
		/// </exception>
		public void Compress (CancellationToken cancellationToken = default)
		{
			var ic = QueueCompressCommand (cancellationToken);

			engine.Run (ic);

			ProcessCompressResponse (ic);
		}

		bool TryQueueEnableQuickResyncCommand (CancellationToken cancellationToken, [NotNullWhen (true)] out ImapCommand? ic)
		{
			CheckDisposed ();
			CheckConnected ();
			CheckAuthenticated ();

			if (engine.State != ImapEngineState.Authenticated)
				throw new InvalidOperationException ("QRESYNC needs to be enabled immediately after authenticating.");

			if ((engine.Capabilities & ImapCapabilities.QuickResync) == 0)
				throw new NotSupportedException ("The IMAP server does not support the QRESYNC extension.");

			if (engine.QResyncEnabled) {
				ic = null;
				return false;
			}

			ic = engine.QueueCommand (cancellationToken, null, "ENABLE QRESYNC CONDSTORE\r\n");

			return true;
		}

		void ProcessEnableResponse (ImapCommand ic)
		{
			ic.ThrowIfNotOk ("ENABLE");

View on GitHub (pinned to 9d3859a785)