{"record":{"id":"35dd011945c61bba","repo":"OrchardCMS/OrchardCore","slug":"invalid-term-in-terms-query","errorCode":null,"errorMessage":"Invalid term in terms query","messagePattern":"Invalid term in terms query","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.Lucene.Core/QueryProviders/Filters/TermsFilterProvider.cs","lineNumber":36,"sourceCode":"        {\n            return null;\n        }\n\n        var queryObj = filter.AsObject();\n        var first = queryObj.First();\n\n        var field = first.Key;\n        var boolQuery = new BooleanQuery();\n\n        switch (first.Value.GetValueKind())\n        {\n            case JsonValueKind.Array:\n\n                foreach (var item in first.Value.AsArray())\n                {\n                    if (item.GetValueKind() != JsonValueKind.String)\n                    {\n                        throw new ArgumentException($\"Invalid term in terms query\");\n                    }\n\n                    boolQuery.Add(new TermQuery(new Term(field, item.Value<string>())), Occur.SHOULD);\n                }\n\n                break;\n\n            case JsonValueKind.Object:\n                throw new ArgumentException(\"The terms lookup query is not supported\");\n\n            default: throw new ArgumentException(\"Invalid terms query\");\n        }\n\n        booleanQuery.Add(boolQuery, Occur.MUST);\n        var queryFilter = new QueryWrapperFilter(boolQuery);\n\n        return new FilteredQuery(booleanQuery, queryFilter);\n    }","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.Lucene.Core/QueryProviders/Filters/TermsFilterProvider.cs#L18-L54","documentation":"TermsFilterProvider.CreateFilteredQuery builds a Lucene terms filter from a JSON value. When the JSON value for the field is an array, every element must be a JSON string that becomes a TermQuery. This error is thrown when an element of the array is not a string (e.g. number, boolean, object, or null), because Lucene terms must be text.","triggerScenarios":"Calling CreateFilteredQuery with a filter JSON like {\"field\": [1, 2]} or {\"field\": [\"a\", true]} where any array element is a non-string JSON value.","commonSituations":"Client queries built from untyped user input or deserialized from a language that coerces numbers/booleans; copy-pasted Elasticsearch queries with numeric terms; hand-written JSON filters with accidental non-string entries.","solutions":["Quote every element in the terms array as a JSON string (e.g. [\"1\", \"2\"] instead of [1, 2]).","Validate the array client-side before sending, rejecting any non-string element.","Catch ArgumentException around CreateFilteredQuery and return a 400 response with a clear message."],"exampleFix":"// before\n{\"status\": [1, 2]}\n// after\n{\"status\": [\"1\", \"2\"]}","handlingStrategy":"validation","validationCode":"if (filter.Value.ValueKind != JsonValueKind.Array || filter.Value.EnumerateArray().Any(i => i.ValueKind != JsonValueKind.String))\n    throw new ArgumentException(\"terms filter requires an array of JSON strings\");","typeGuard":"static bool IsValidTermsFilter(JsonElement el) =>\n    el.ValueKind == JsonValueKind.Array && el.EnumerateArray().All(i => i.ValueKind == JsonValueKind.String);","tryCatchPattern":"try { var query = provider.CreateFilteredQuery(context, filter); }\ncatch (ArgumentException ex) { return BadRequest($\"Invalid terms filter: {ex.Message}\"); }","preventionTips":["Always emit terms arrays as JSON strings, even for numeric-looking values.","Validate filter JSON schema before dispatching to the query provider.","Write unit tests covering each JSON value kind per filter provider."],"tags":["lucene","query-validation","json"],"backgroundTag":"invalid-argument-value","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}