jstedfast/MailKit · error · NotSupportedException

The PARTIAL extension only supports UID-based FETCH…

Error message

The PARTIAL extension only supports UID-based FETCH requests.

What it means

CheckCanFetch(IList<int>, IFetchRequest) throws this NotSupportedException when request.PartialRange is set on an index-based (sequence number) Fetch call. The PARTIAL fetch modifier is only defined for UID FETCH commands, so MailKit forbids combining PartialRange with index-based Fetch/FetchAsync.

Solutions

  1. Use the UID-based overload: convert indexes to UIDs (e.g. via folder.Fetch UIDs / GetMessageUids) and call Fetch(uids, request)
  2. Create a separate IFetchRequest without PartialRange for index-based fetches
  3. Set request.PartialRange = null before index-based Fetch calls

Example fix

// before
request.PartialRange = partial;
var summaries = folder.Fetch(indexes, request); // throws
// after
request.PartialRange = null;
var summaries = folder.Fetch(indexes, request); // or use folder.Fetch(uids, requestWithPartial)
Defensive patterns

Strategy: validation

Validate before calling

if (request.PartialRange.HasValue)
    throw new InvalidOperationException("Use the UID-based Fetch overload for PartialRange.");
var summaries = folder.Fetch(indexes, request);

Try / catch

try {
    summaries = folder.Fetch(indexes, request);
} catch (NotSupportedException ex) when (ex.Message.Contains("UID-based")) {
    request.PartialRange = null;
    summaries = folder.Fetch(indexes, request);
}

Prevention

When it happens

Trigger: Calling Fetch(IList<int> indexes, IFetchRequest request) or FetchAsync with request.PartialRange.HasValue — PARTIAL requires the UID-based Fetch(uids, request) overload.

Common situations: Reusing a single FetchRequest object (with PartialRange set) across both UID and index fetch paths; switching code from UID fetch to index fetch without clearing the request.

Related errors


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

Appendix: source

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

			if (previewText)
				await GetPreviewTextAsync (ctx, cancellationToken).ConfigureAwait (false);

			return ctx.Messages.AsReadOnly ();
		}

		bool CheckCanFetch (IList<int> indexes, IFetchRequest request)
		{
			if (indexes == null)
				throw new ArgumentNullException (nameof (indexes));

			if (request == null)
				throw new ArgumentNullException (nameof (request));

			if (request.ChangedSince.HasValue && !supportsModSeq)
				throw new NotSupportedException ("The ImapFolder does not support mod-sequences.");

			if (request.PartialRange.HasValue)
				throw new NotSupportedException ("The PARTIAL extension only supports UID-based FETCH requests.");

			CheckState (true, false);
			CheckAllowIndexes ();

			return indexes.Count > 0 && !IsEmptyFetchRequest (request);
		}

		ImapCommand QueueFetchCommand (IList<int> indexes, IFetchRequest request, CancellationToken cancellationToken, out bool previewText)
		{
			var query = FormatSummaryItems (Engine, request, out previewText);
			var set = ImapUtils.FormatIndexSet (Engine, indexes);
			var changedSince = string.Empty;

			if (request.ChangedSince.HasValue)
				changedSince = string.Format (CultureInfo.InvariantCulture, " (CHANGEDSINCE {0})", request.ChangedSince.Value);

			var command = string.Format ("FETCH {0} {1}{2}\r\n", set, query, changedSince);
			var ic = new ImapCommand (Engine, cancellationToken, this, command);

View on GitHub (pinned to 9d3859a785)