{"record":{"id":"3f7e14d1b4c714e8","repo":"jstedfast/MailKit","slug":"untagged-handlers-must-be-registered-before-the-command-has","errorCode":null,"errorMessage":"Untagged handlers must be registered before the command has been queued.","messagePattern":"Untagged handlers must be registered before the command has been queued\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"MailKit/Net/Imap/ImapCommand.cs","lineNumber":493,"sourceCode":"\t\t/// <param name=\"handler\">The handler.</param>\n\t\t/// <exception cref=\"System.ArgumentNullException\">\n\t\t/// <para><paramref name=\"atom\"/> is <see langword=\"null\" />.</para>\n\t\t/// <para>-or-</para>\n\t\t/// <para><paramref name=\"handler\"/> is <see langword=\"null\" />.</para>\n\t\t/// </exception>\n\t\t/// <exception cref=\"System.InvalidOperationException\">\n\t\t/// Untagged handlers must be registered before the command has been queued.\n\t\t/// </exception>\n\t\tpublic void RegisterUntaggedHandler (string atom, ImapUntaggedHandler handler)\n\t\t{\n\t\t\tif (atom == null)\n\t\t\t\tthrow new ArgumentNullException (nameof (atom));\n\n\t\t\tif (handler == null)\n\t\t\t\tthrow new ArgumentNullException (nameof (handler));\n\n\t\t\tif (Status != ImapCommandStatus.Created)\n\t\t\t\tthrow new InvalidOperationException (\"Untagged handlers must be registered before the command has been queued.\");\n\n\t\t\tUntaggedHandlers.Add (atom, handler);\n\t\t}\n\n\t\tstatic bool IsOkNoOrBad (string atom, out ImapCommandResponse response)\n\t\t{\n\t\t\tif (atom.Equals (\"OK\", StringComparison.OrdinalIgnoreCase)) {\n\t\t\t\tresponse = ImapCommandResponse.Ok;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (atom.Equals (\"NO\", StringComparison.OrdinalIgnoreCase)) {\n\t\t\t\tresponse = ImapCommandResponse.No;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (atom.Equals (\"BAD\", StringComparison.OrdinalIgnoreCase)) {\n\t\t\t\tresponse = ImapCommandResponse.Bad;","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/Net/Imap/ImapCommand.cs#L475-L511","documentation":"RegisterUntaggedHandler must be called while the ImapCommand is still in ImapCommandStatus.Created; once the command has been queued to the engine the server may already be streaming responses, so late registration is rejected with this InvalidOperationException. It protects against silently dropping untagged responses.","triggerScenarios":"Calling command.RegisterUntaggedHandler(...) after QueueCommand/queueing (or after the command started running); MailKit's own Queue* helpers register handlers before queuing, so this surfaces in custom command pipelines.","commonSituations":"Custom IMAP extension code that constructs an ImapCommand, queues it, then tries to attach handlers conditionally; refactors that moved handler registration after an enqueue call.","solutions":["Move all RegisterUntaggedHandler calls to immediately after ImapCommand construction and before queuing.","If the command status is unknown, check command.Status == ImapCommandStatus.Created before registering.","Restructure so handler choice is decided before enqueue, or build a new command instead of mutating a queued one."],"exampleFix":"// before\nengine.QueueCommand(ic, r => ...);\nic.RegisterUntaggedHandler(\"FETCH\", handler);\n\n// after\nic.RegisterUntaggedHandler(\"FETCH\", handler);\nengine.QueueCommand(ic, r => ...);","handlingStrategy":"validation","validationCode":"if (ic.Status != ImapCommandStatus.Created)\n    throw new InvalidOperationException(\"Cannot register untagged handler: command already queued\");\nic.RegisterUntaggedHandler(atom, handler);","typeGuard":null,"tryCatchPattern":"try { ic.RegisterUntaggedHandler(atom, handler); } catch (InvalidOperationException) { log.Warn(\"Handler registered too late; rebuild command\"); }","preventionTips":["Register handlers immediately after constructing ImapCommand, before any queue call.","Never mutate a command after enqueueing; build a fresh one instead.","Code-review custom IMAP command helpers for construct->register->queue ordering."],"tags":["imap","command-lifecycle","invalid-state","untagged-response"],"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"}