jstedfast/MailKit · error · ImapProtocolException
Syntax error in untagged EXPUNGE response. Unexpected…
Error message
Syntax error in untagged EXPUNGE response. Unexpected message index: 0
What it means
Thrown when an untagged EXPUNGE response reports message index 0, which is impossible: IMAP sequence numbers are 1-based. MailKit throws because subtracting 1 would yield an invalid index (-1) for OnExpunge. This is raised in the synchronous untagged-response processing path.
Solutions
- Inspect the protocol log to confirm the server emitted `* 0 EXPUNGE`
- Update or fix the IMAP server — a 1-based sequence number of 0 is a server bug per RFC 3501
- Upgrade MailKit; check release notes for relaxed handling of zero-valued untagged responses
- If a proxy rewrites sequence numbers, correct its 1-based indexing
- Work around by wrapping folder operations in try/catch for ImapProtocolException and issuing NOOP/re-sync if your server is known-buggy
Example fix
// before // server: * 0 EXPUNGE // after // server: * 1 EXPUNGE (1-based sequence number per RFC 3501)
Defensive patterns
Strategy: try-catch
Try / catch
try {
folder.NoOp (); // drains untagged responses, may hit EXPUNGE parse
} catch (ImapProtocolException ex) {
logger.LogError (ex, "Server sent '* 0 EXPUNGE' - server bug");
// resync: reopen the folder to rebuild the message index
folder.Close (false);
folder.Open (FolderAccess.ReadWrite);
} Prevention
- Audit your IMAP server/proxy for 0-based sequence-number bugs (compare to Courier `* 0 FETCH` quirk, MailKit issue #428)
- Run protocol logging in staging with realistic expunge workloads
- Keep MailKit updated for quirk-mode handling
- On known-buggy servers, plan periodic folder re-open/resync
When it happens
Trigger: The server sends `* 0 EXPUNGE` while MailKit processes untagged responses during a synchronous command (e.g. after a command issued on ImapFolder, or during NoOp/Check when updates are drained).
Common situations: Known bug class in older/broken IMAP servers (similar to the Courier-IMAP `* 0 FETCH` quirk documented in MailKit issue #428); custom or in-house server implementations emitting 0-based indices; buggy proxies translating responses.
Related errors
- STATUS
- Value cannot be null. (Parameter 'uids')
- All folders must be ImapFolders.
- An annotation entry cannot be empty.
- An annotation entry must begin with a '/' character.
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/f56ac788711874ed.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Net/Imap/ImapEngine.cs:2927
}
} else {
if (uint.TryParse (atom, NumberStyles.None, CultureInfo.InvariantCulture, out uint number)) {
// we probably have something like "* 1 EXISTS"
token = ReadToken (cancellationToken);
AssertToken (token, ImapTokenType.Atom, "Syntax error in untagged response. {0}", token);
atom = (string) token.Value;
if (ic.UntaggedHandlers.TryGetValue (atom, out handler)) {
// the command registered an untagged handler for this atom...
handler (this, ic, (int) number - 1, false).GetAwaiter ().GetResult ();
} else if (folder != null) {
if (atom.Equals ("EXISTS", StringComparison.OrdinalIgnoreCase)) {
folder.OnExists ((int) number);
} else if (atom.Equals ("EXPUNGE", StringComparison.OrdinalIgnoreCase)) {
if (number == 0)
throw UnexpectedToken ("Syntax error in untagged EXPUNGE response. Unexpected message index: 0");
folder.OnExpunge ((int) number - 1);
} else if (atom.Equals ("FETCH", StringComparison.OrdinalIgnoreCase)) {
// Apparently Courier-IMAP (2004) will reply with "* 0 FETCH ..." sometimes.
// See https://github.com/jstedfast/MailKit/issues/428 for details.
//if (number == 0)
// throw UnexpectedToken ("Syntax error in untagged FETCH response. Unexpected message index: 0");
folder.OnUntaggedFetchResponse (this, (int) number - 1, cancellationToken);
} else if (atom.Equals ("RECENT", StringComparison.OrdinalIgnoreCase)) {
folder.OnRecent ((int) number);
} else {
//Debug.WriteLine ("Unhandled untagged response: * {0} {1}", number, atom);
}
} else {
//Debug.WriteLine ("Unhandled untagged response: * {0} {1}", number, atom);
}
View on GitHub (pinned to 9d3859a785)