{"record":{"id":"9a8c680cb463e4e0","repo":"jstedfast/MailKit","slug":"an-imapfolder-has-not-been-opened","errorCode":null,"errorMessage":"An ImapFolder has not been opened.","messagePattern":"An ImapFolder has not been opened\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"MailKit/Net/Imap/ImapClient.cs","lineNumber":1925,"sourceCode":"\t\t\tengine.Run (ic);\n\n\t\t\tProcessNoOpResponse (ic);\n\t\t}\n\n\t\tvoid CheckCanIdle (CancellationToken doneToken)\n\t\t{\n\t\t\tif (!doneToken.CanBeCanceled)\n\t\t\t\tthrow new ArgumentException (\"The doneToken must be cancellable.\", nameof (doneToken));\n\n\t\t\tCheckDisposed ();\n\t\t\tCheckConnected ();\n\t\t\tCheckAuthenticated ();\n\n\t\t\tif ((engine.Capabilities & ImapCapabilities.Idle) == 0)\n\t\t\t\tthrow new NotSupportedException (\"The IMAP server does not support the IDLE extension.\");\n\n\t\t\tif (engine.State != ImapEngineState.Selected)\n\t\t\t\tthrow new InvalidOperationException (\"An ImapFolder has not been opened.\");\n\t\t}\n\n\t\tImapCommand QueueIdleCommand (ImapIdleContext context, CancellationToken cancellationToken)\n\t\t{\n\t\t\tvar ic = engine.QueueCommand (cancellationToken, null, \"IDLE\\r\\n\");\n\t\t\tic.ContinuationHandler = context.ContinuationHandler;\n\t\t\tic.UserData = context;\n\n\t\t\treturn ic;\n\t\t}\n\n\t\tstatic void ProcessIdleResponse (ImapCommand ic)\n\t\t{\n\t\t\tic.ThrowIfNotOk (\"IDLE\");\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Toggle the <see cref=\"ImapClient\"/> into the IDLE state.","sourceCodeStart":1907,"sourceCodeEnd":1943,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/Net/Imap/ImapClient.cs#L1907-L1943","documentation":"CheckCanIdle throws this InvalidOperationException when the engine state is not Selected, i.e. no folder (ImapFolder) has been opened on the connection before starting IDLE. IDLE only makes sense within the selected-state of a mailbox.","triggerScenarios":"Calling IdleAsync before any folder.Open(...) succeeded; the selected folder was closed or the connection reset to authenticated state; calling idle on a raw ImapClient connection after folder open failed.","commonSituations":"Startup ordering bug where idle listener starts before folder selection completes; folder.Open threw earlier and the code continued to idle; reconnect logic re-established connection but did not re-select the folder.","solutions":["Open a folder first: var folder = client.GetFolder(...); folder.Open(FolderAccess.ReadWrite);","Re-select the folder after any reconnect before resuming IDLE","Check folder.IsOpen before starting the idle loop"],"exampleFix":"// before\nawait client.IdleAsync(null, doneToken);\n// after\nvar inbox = client.Inbox;\nawait inbox.OpenAsync(FolderAccess.ReadWrite);\nawait inbox.IdleAsync(doneToken);","handlingStrategy":"validation","validationCode":"if (folder == null || !folder.IsOpen)\n    await folder.OpenAsync(FolderAccess.ReadWrite);","typeGuard":"bool ReadyForIdle(IMailFolder f) => f is { IsOpen: true };","tryCatchPattern":"try { await folder.IdleAsync(doneToken); }\ncatch (InvalidOperationException) { await folder.OpenAsync(FolderAccess.ReadWrite); await folder.IdleAsync(doneToken); }","preventionTips":["Always Open a folder before starting IDLE","Re-open the folder after every reconnect","Sequence startup: connect -> authenticate -> open folder -> idle"],"tags":["imap","idle","state","mailkit"],"backgroundTag":"invalid-state-transition","analyzedSha":"9d3859a7855e3e17582c07fd01972b8e262bf176","analyzedAt":"2026-09-15T15:46:11.592Z","contentChangedAt":"2026-09-15T15:46:11.592Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}