jstedfast/MailKit · error · ArgumentException

No keywords specified.

Error message

No keywords specified.

What it means

After collecting valid keywords, HasKeywords throws ArgumentException with 'No keywords specified.' if the enumerable was empty (zero valid elements), since AND-ing zero queries is undefined for an IMAP search.

Solutions

  1. Check count before calling: `if (keywords.Any()) query = SearchQuery.HasKeywords(keywords);` else use SearchQuery.All or skip the criterion.
  2. Return early from your search-builder when the keyword list is empty.
  3. Require at least one keyword at the UI/validation layer.

Example fix

// before
var query = SearchQuery.HasKeywords(selectedTags); // empty
// after
var query = selectedTags.Count > 0
    ? SearchQuery.HasKeywords(selectedTags)
    : SearchQuery.All;
Defensive patterns

Strategy: validation

Validate before calling

var list = keywords?.ToList();
if (list == null || list.Count == 0)
    return SearchQuery.All;
var query = SearchQuery.HasKeywords(list);

Type guard

bool IsNonEmptyKeywordList(IEnumerable<string> kws) => kws != null && kws.Any(k => !string.IsNullOrEmpty(k));

Try / catch

try { query = SearchQuery.HasKeywords(keywords); }
catch (ArgumentException ex) { query = SearchQuery.All; }

Prevention

When it happens

Trigger: Calling SearchQuery.HasKeywords with an empty array/List, an empty Split result, or an empty LINQ query.

Common situations: User submitted no tags but the code still builds a keyword criterion; filtering removed all elements; a config array is present but empty.

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


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

Appendix: source

Thrown at MailKit/Search/SearchQuery.cs:550

		/// <para>-or-</para>
		/// <para>No keywords were given.</para>
		/// </exception>
		public static SearchQuery HasKeywords (IEnumerable<string> keywords)
		{
			if (keywords == null)
				throw new ArgumentNullException (nameof (keywords));

			var list = new List<SearchQuery> ();

			foreach (var keyword in keywords) {
				if (string.IsNullOrEmpty (keyword))
					throw new ArgumentException ("Cannot search for null or empty keywords.", nameof (keywords));

				list.Add (new TextSearchQuery (SearchTerm.Keyword, keyword));
			}

			if (list.Count == 0)
				throw new ArgumentException ("No keywords specified.", nameof (keywords));

			var query = list[0];
			for (int i = 1; i < list.Count; i++)
				query = query.And (list[i]);

			return query;
		}

		/// <summary>
		/// Match messages that do not have the specified keyword set.
		/// </summary>
		/// <remarks>
		/// <para>Matches messages that do not have the specified keyword set.</para>
		/// <para>A keyword is a user-defined message flag that can be set (or unset) on a message.</para>
		/// <note type="note">This is equivalent to the <c>UNKEYWORD</c> search key as defined in <a href="https://datatracker.ietf.org/doc/html/rfc3501#section-6.4.4">rfc3501</a>.</note>
		/// </remarks>
		/// <returns>A <see cref="TextSearchQuery"/>.</returns>
		/// <param name="keyword">The keyword.</param>

View on GitHub (pinned to 9d3859a785)