{"record":{"id":"4fe1d61d05cc8ed0","repo":"jstedfast/MailKit","slug":"no-keywords-specified","errorCode":null,"errorMessage":"No keywords specified.","messagePattern":"No keywords specified\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"MailKit/Search/SearchQuery.cs","lineNumber":550,"sourceCode":"\t\t/// <para>-or-</para>\n\t\t/// <para>No keywords were given.</para>\n\t\t/// </exception>\n\t\tpublic static SearchQuery HasKeywords (IEnumerable<string> keywords)\n\t\t{\n\t\t\tif (keywords == null)\n\t\t\t\tthrow new ArgumentNullException (nameof (keywords));\n\n\t\t\tvar list = new List<SearchQuery> ();\n\n\t\t\tforeach (var keyword in keywords) {\n\t\t\t\tif (string.IsNullOrEmpty (keyword))\n\t\t\t\t\tthrow new ArgumentException (\"Cannot search for null or empty keywords.\", nameof (keywords));\n\n\t\t\t\tlist.Add (new TextSearchQuery (SearchTerm.Keyword, keyword));\n\t\t\t}\n\n\t\t\tif (list.Count == 0)\n\t\t\t\tthrow new ArgumentException (\"No keywords specified.\", nameof (keywords));\n\n\t\t\tvar query = list[0];\n\t\t\tfor (int i = 1; i < list.Count; i++)\n\t\t\t\tquery = query.And (list[i]);\n\n\t\t\treturn query;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Match messages that do not have the specified keyword set.\n\t\t/// </summary>\n\t\t/// <remarks>\n\t\t/// <para>Matches messages that do not have the specified keyword set.</para>\n\t\t/// <para>A keyword is a user-defined message flag that can be set (or unset) on a message.</para>\n\t\t/// <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>\n\t\t/// </remarks>\n\t\t/// <returns>A <see cref=\"TextSearchQuery\"/>.</returns>\n\t\t/// <param name=\"keyword\">The keyword.</param>","sourceCodeStart":532,"sourceCodeEnd":568,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/Search/SearchQuery.cs#L532-L568","documentation":"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.","triggerScenarios":"Calling SearchQuery.HasKeywords with an empty array/List, an empty Split result, or an empty LINQ query.","commonSituations":"User submitted no tags but the code still builds a keyword criterion; filtering removed all elements; a config array is present but empty.","solutions":["Check count before calling: `if (keywords.Any()) query = SearchQuery.HasKeywords(keywords);` else use SearchQuery.All or skip the criterion.","Return early from your search-builder when the keyword list is empty.","Require at least one keyword at the UI/validation layer."],"exampleFix":"// before\nvar query = SearchQuery.HasKeywords(selectedTags); // empty\n// after\nvar query = selectedTags.Count > 0\n    ? SearchQuery.HasKeywords(selectedTags)\n    : SearchQuery.All;","handlingStrategy":"validation","validationCode":"var list = keywords?.ToList();\nif (list == null || list.Count == 0)\n    return SearchQuery.All;\nvar query = SearchQuery.HasKeywords(list);","typeGuard":"bool IsNonEmptyKeywordList(IEnumerable<string> kws) => kws != null && kws.Any(k => !string.IsNullOrEmpty(k));","tryCatchPattern":"try { query = SearchQuery.HasKeywords(keywords); }\ncatch (ArgumentException ex) { query = SearchQuery.All; }","preventionTips":["Guard with .Any() before building keyword criteria.","Decide explicit behavior for the empty case (match all vs. validation error).","Require at least one keyword at the UI/validation layer."],"tags":["argument-validation","empty-collection","search-query","mailkit"],"backgroundTag":"empty-required-field","analyzedSha":"9d3859a7855e3e17582c07fd01972b8e262bf176","analyzedAt":"2026-09-15T15:46:11.592Z","contentChangedAt":"2026-09-15T15:46:11.592Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}