jstedfast/MailKit · error · ArgumentException
No sort order provided.
Error message
No sort order provided.
What it means
MessageThreader.Thread throws this ArgumentException when the orderBy list of OrderBy clauses is non-null but empty. Threading requires at least one sort criterion to order messages within threads, so an empty collection is rejected up front.
Solutions
- Pass at least one OrderBy value, e.g. new List<OrderBy> { OrderBy.Date }
- If the list is built dynamically, validate Count > 0 before calling Thread and choose a sensible default sort
- Check that config/serialization of the sort preferences actually produced entries
Example fix
// before
var orderBy = new List<OrderBy>();
var tree = threader.Thread(messages, ThreadingAlgorithm.References, orderBy);
// after
var orderBy = new List<OrderBy> { OrderBy.Date, OrderBy.Subject };
var tree = threader.Thread(messages, ThreadingAlgorithm.References, orderBy); Defensive patterns
Strategy: validation
Validate before calling
if (orderBy == null || orderBy.Count == 0)
orderBy = new List<OrderBy> { OrderBy.Date }; // or throw earlier with context Type guard
bool HasSortOrder(IList<OrderBy> orderBy) => orderBy != null && orderBy.Count > 0;
Try / catch
try {
tree = threader.Thread(messages, algorithm, orderBy);
} catch (ArgumentException ex) when (ex.ParamName == "orderBy") {
// fall back to a default sort or skip threading
} Prevention
- Validate the OrderBy list has Count > 0 before calling Thread
- Provide a default sort order when preferences are empty
- Centralize threading behind a helper that enforces a fallback sort
When it happens
Trigger: Calling MessageThreader.Thread(messages, algorithm, orderBy) with a valid (non-null) but zero-element IList<OrderBy>, e.g. `new List<OrderBy>()` or a filtered list that ended up empty.
Common situations: Building the sort-order list dynamically from user preferences or config where no sort keys were selected; copy-pasting a Thread call from sample code and deleting the OrderBy items; deserializing sort settings from an empty JSON array.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- No indexes were specified.
- No keywords specified.
- Cannot search for an empty set of unique identifiers.
- array
- uri
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/179af8425db02846.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/MessageThreader.cs:452
/// </exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <paramref name="algorithm"/> is not a valid threading algorithm.
/// </exception>
/// <exception cref="System.ArgumentException">
/// <para><paramref name="messages"/> contains one or more items that is missing information needed for threading or sorting.</para>
/// <para>-or-</para>
/// <para><paramref name="orderBy"/> is an empty list.</para>
/// </exception>
public static IList<MessageThread> Thread (this IEnumerable<IMessageSummary> messages, ThreadingAlgorithm algorithm, IList<OrderBy> orderBy)
{
if (messages == null)
throw new ArgumentNullException (nameof (messages));
if (orderBy == null)
throw new ArgumentNullException (nameof (orderBy));
if (orderBy.Count == 0)
throw new ArgumentException ("No sort order provided.", nameof (orderBy));
switch (algorithm) {
case ThreadingAlgorithm.OrderedSubject: return ThreadBySubject (messages, orderBy);
case ThreadingAlgorithm.References: return ThreadByReferences (messages, orderBy);
default: throw new ArgumentOutOfRangeException (nameof (algorithm));
}
}
static bool IsForward (string subject, int index)
{
return (subject[index] == 'F' || subject[index] == 'f') &&
(subject[index + 1] == 'W' || subject[index + 1] == 'w') &&
(subject[index + 2] == 'D' || subject[index + 2] == 'd') &&
subject[index + 3] == ':';
}
static bool IsReply (string subject, int index)
{View on GitHub (pinned to 9d3859a785)