zincsearch/zincsearch · error
ErrorTypeIllegalArgumentException
ErrorTypeIllegalArgumentException
Error message
[multi_match] unknown operator %s
What it means
MultiMatchQuery validates the operator string supplied in the multi_match query body. Only "OR" and "AND" (case-sensitive) map to bluge match operators; anything else is rejected as an illegal argument. This guards against invalid operator values being passed down to the bluge search layer.
Source
Thrown at pkg/uquery/query/multi_match.go:74
// return nil, errors.New(errors.ErrorTypeParsingException, fmt.Sprintf("[multi_match] unknown field [%s]", k))
}
}
var zer *analysis.Analyzer
if value.Analyzer != "" {
zer, _ = zincanalysis.QueryAnalyzer(analyzers, value.Analyzer)
}
var operator bluge.MatchQueryOperator = bluge.MatchQueryOperatorOr
if value.Operator != "" {
op := strings.ToUpper(value.Operator)
switch op {
case "OR":
operator = bluge.MatchQueryOperatorOr
case "AND":
operator = bluge.MatchQueryOperatorAnd
default:
return nil, errors.New(errors.ErrorTypeIllegalArgumentException, fmt.Sprintf("[multi_match] unknown operator %s", op))
}
}
subq := bluge.NewBooleanQuery()
if value.MinimumShouldMatch != nil {
minValue, err := zutils.CalculateMin(len(value.Fields), value.MinimumShouldMatch)
if err != nil {
return nil, errors.New(errors.ErrorTypeXContentParseException, fmt.Sprintf("[multi_match] unsupported MinimumShouldMatch value: %v", err))
}
subq.SetMinShould(minValue) // lgtm[go/hardcoded-credentials]
}
if value.Boost >= 0 {
subq.SetBoost(value.Boost)
}
for _, field := range value.Fields {
subqq := bluge.NewMatchQuery(value.Query).SetField(field).SetOperator(operator)
if zer != nil {
subqq.SetAnalyzer(zer)View on GitHub (pinned to dd2f8afd65)
Solutions
- Set the operator to the exact uppercase string "OR" or "AND" in the multi_match body
- Trim/uppercase the operator value client-side before sending
- Check the request JSON for stray whitespace or casing in the operator field
- Omit the operator field entirely to use the default
Example fix
// before
{"multi_match": {"query": "foo", "fields": ["title"], "operator": "or"}}
// after
{"multi_match": {"query": "foo", "fields": ["title"], "operator": "OR"}} Defensive patterns
Strategy: validation
Validate before calling
op, _ := body["operator"].(string)
if op != "" && op != "OR" && op != "AND" {
return fmt.Errorf("operator must be OR or AND, got %q", op)
} Type guard
func isValidOperator(v interface{}) bool {
s, ok := v.(string)
return !ok || s == "OR" || s == "AND"
} Try / catch
q, err := uquery.Query(body)
if err != nil {
var e *errors.Error
if errors.As(err, &e) && e.Type == errors.ErrorTypeIllegalArgumentException {
// fix operator and retry
}
} Prevention
- Always use the uppercase literals "OR"/"AND" for operator
- Normalize operator input with strings.ToUpper(strings.TrimSpace(op)) before sending
- Add request-body validation at the API edge
When it happens
Trigger: Calling MultiMatchQuery (via Query / ParseQueryDSL) with a multi_match body whose "operator" field is anything other than the exact strings "OR" or "AND" — e.g. "or", "and", "or " with whitespace, "SHOULD", or a misspelling.
Common situations: Copied ES DSL with lowercase operator "or"; dynamically built queries injecting user input into operator; typos like "ANND"; clients that default to Go-style naming instead of ES upper-case constants.
Related errors
- ErrorTypeXContentParseException
- invalid_argument
- invalid_argument
- index ${name} does not exists
- bulk index data format error
AI-assisted analysis of zincsearch/zincsearch@dd2f8afd65 (2026-09-03).
Data as JSON: /api/errors/80428233bfda2394.
Report an issue: GitHub.