jstedfast/MailKit · error · NotSupportedException

The set of unique identifiers is too large to fetch with a…

Error message

The set of unique identifiers is too large to fetch with a partial range.

What it means

CreateFetchCommands throws this NotSupportedException when a PARTIAL fetch would require more than one FETCH command. The PARTIAL modifier applies per-command, so MailKit would have to split large UID sets into multiple commands, and splitting would restart the partial offset for each command, changing the request semantics. Rather than return wrong data, it throws.

Solutions

  1. Batch the UID list so each call stays within the single-command limit (fetch in chunks of ~1000 or fewer UIDs)
  2. Fetch by sequence-number range or use a single UID range (e.g. new UniqueIdRange(...)) that maps to one command
  3. Drop PartialRange if you don't need partial semantics, allowing the normal multi-command splitting

Example fix

// before
var summaries = folder.Fetch(allUids, requestWithPartialRange); // allUids.Count = 5000
// after
foreach (var chunk in Chunk(allUids, 1000))
    folder.Fetch(chunk, requestWithPartialRange); // each within a single FETCH command
Defensive patterns

Strategy: validation

Validate before calling

const int MaxUidsPerPartialFetch = 1000;
if (request.PartialRange.HasValue && uids.Count > MaxUidsPerPartialFetch)
    throw new InvalidOperationException("Chunk the UID set before a partial fetch.");

Try / catch

try {
    summaries = folder.Fetch(uids, request);
} catch (NotSupportedException ex) when (ex.Message.Contains("partial range")) {
    foreach (var chunk in Chunk(uids, 1000))
        foreach (var s in folder.Fetch(chunk, request))
            yield return s;
}

Prevention

When it happens

Trigger: Calling Fetch/FetchAsync by UID with request.PartialRange set and a UID set so large (typically > ~1000 UIDs, Engine's per-command batch size) that MailKit splits it into multiple UID FETCH commands.

Common situations: Resuming download of a large mailbox with PartialRange while passing thousands of UIDs at once; resync jobs that pass UniqueIdRange covering every message combined with partial fetch.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15). Data as JSON: /api/errors/dbc5961bd254c3ec. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/Net/Imap/ImapFolderFetch.cs:1147

				command.Append (')');
			}

			command.Append ("\r\n");

			return command.ToString ();
		}

		IEnumerable<ImapCommand> CreateFetchCommands (IList<UniqueId> uids, IFetchRequest request, string command, CancellationToken cancellationToken)
		{
			var commands = Engine.CreateCommands (cancellationToken, this, command, uids);

			if (request.PartialRange.HasValue) {
				// Note: The PARTIAL fetch modifier applies to each FETCH command individually, so splitting the
				// set of UIDs into multiple FETCH commands would change the semantics of the request.
				var list = new List<ImapCommand> (commands);

				if (list.Count > 1)
					throw new NotSupportedException ("The set of unique identifiers is too large to fetch with a partial range.");

				return list;
			}

			return commands;
		}

		static int EstimateInitialCapacity (IList<UniqueId> uids)
		{
			if (uids is UniqueIdRange || uids is UniqueIdSet) {
				// UniqueIdRange is likely to refer to UIDs that have not yet been assigned or have been expunged,
				// so cap our maximum initial capacity to 1024 (a reasonable limit?).
				return Math.Min (uids.Count, 1024);
			}

			// If the user supplied an exact set of UIDs, then we'll assume they all exist
			// and therefore we can use the capacity of `uids` as our initial capacity.
			return uids.Count;

View on GitHub (pinned to 9d3859a785)