OrchardCMS/OrchardCore · error · ArgumentException

Invalid term query

Error message

Invalid term query

What it means

TermFilterProvider.CreateFilteredQuery builds a Lucene TermQuery from a term filter. The term value must be in a supported shape (an object with "value"/optional "boost", or the accepted simple form); if the value's JSON kind reaches the switch default, the provider throws ArgumentException("Invalid term query") because it cannot derive a term from the supplied JSON.

Solutions

  1. Provide a scalar value or an object with a "value" property: {"term": {"Status": {"value": "Published"}}}.
  2. For multiple values, issue multiple term filters or use the match filter instead of an array under term.
  3. Never omit "value" when using the object form; put options like boost alongside a present "value".
  4. Coerce null/undefined filter values to a concrete string (or drop the filter) before calling CreateFilteredQuery.

Example fix

// before
{"term": {"Status": {"boost": 2}}}
// after
{"term": {"Status": {"value": "Published", "boost": 2}}}
Defensive patterns

Strategy: validation

Validate before calling

if (filter.TryGetPropertyValue(field, out var v))
{
    var ok = v.ValueKind is JsonValueKind.String or JsonValueKind.Number or JsonValueKind.Object;
    if (ok && v.ValueKind == JsonValueKind.Object)
        ok = v.AsObject().TryGetPropertyValue("value", out _);
    if (!ok)
        throw new InvalidOperationException($"term filter for '{field}' needs a scalar value or object with 'value'.");
}

Type guard

static bool IsValidTermValue(JsonElement v) =>
    v.ValueKind is JsonValueKind.String or JsonValueKind.Number ||
    (v.ValueKind == JsonValueKind.Object && v.AsObject().TryGetPropertyValue("value", out _));

Try / catch

try
{
    var query = provider.CreateFilteredQuery(context);
}
catch (ArgumentException ex) when (ex.Message.Contains("Invalid term"))
{
    _logger.LogError(ex, "Unsupported term filter value: {Json}", filterJson);
    throw new QueryValidationException("term filters require a scalar or object with 'value'.", ex);
}

Prevention

When it happens

Trigger: Calling CreateFilteredQuery with {"term": {"Status": ["a", "b"]}} (array), {"term": {"Status": {"boost": 2}}} (object without "value"), or {"term": {"Status": null}} — value kinds that fall through to the default branch.

Common situations: Using Elasticsearch-style term arrays for multi-value matching (not supported here; use a different filter); an object carrying only boost with the value removed; null values from dynamic query builders for empty filters; copy-paste between term and match filter syntaxes.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/2de2fdc67957ebc9. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore/OrchardCore.Lucene.Core/QueryProviders/Filters/TermFilterProvider.cs:43

        // A term query has only one member, which can either be a string or an object
        TermQuery termQuery;

        switch (first.Value.GetValueKind())
        {
            case JsonValueKind.String:
                termQuery = new TermQuery(new Term(first.Key, first.Value.ToString()));
                break;
            case JsonValueKind.Object:
                var obj = first.Value.AsObject();
                var value = obj["value"].Value<string>();
                termQuery = new TermQuery(new Term(first.Key, value));

                if (obj.TryGetPropertyValue("boost", out var boost))
                {
                    termQuery.Boost = boost.Value<float>();
                }
                break;
            default: throw new ArgumentException("Invalid term query");
        }

        booleanQuery.Add(termQuery, Occur.MUST);
        var queryFilter = new QueryWrapperFilter(termQuery);

        return new FilteredQuery(booleanQuery, queryFilter);
    }
}

View on GitHub (pinned to 4306c0717f)