{"record":{"id":"6ef45ce6245fd082","repo":"Tencent/WeKnora","slug":"logical-operator-s-requires-an-array-of-condition","errorCode":null,"errorMessage":"logical operator %s requires an array of conditions","messagePattern":"logical operator (.+?) requires an array of conditions","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/repository/retriever/milvus/filter.go","lineNumber":267,"sourceCode":"\t\tField    string `json:\"field,omitempty\"`\n\t\tOperator string `json:\"operator\"`\n\t\tValue    any    `json:\"value,omitempty\"`\n\t}\n\n\tvar aux Alias\n\tif err := json.Unmarshal(data, &aux); err != nil {\n\t\treturn err\n\t}\n\n\tc.Field = aux.Field\n\tc.Operator = strings.ToLower(aux.Operator)\n\n\t// Handle logical operators (and/or) - Value should be []*UniversalFilterCondition\n\tif c.Operator == operatorAnd || c.Operator == operatorOr {\n\t\t// Value can be an array of conditions\n\t\tvalueSlice, ok := aux.Value.([]any)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"logical operator %s requires an array of conditions\", c.Operator)\n\t\t}\n\n\t\tconditions := make([]*universalFilterCondition, 0, len(valueSlice))\n\t\tfor i, v := range valueSlice {\n\t\t\tcondBytes, err := json.Marshal(v)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to marshal condition at index %d: %w\", i, err)\n\t\t\t}\n\n\t\t\tvar cond universalFilterCondition\n\t\t\tif err := json.Unmarshal(condBytes, &cond); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to unmarshal condition at index %d: %w\", i, err)\n\t\t\t}\n\t\t\tconditions = append(conditions, &cond)\n\t\t}\n\t\tc.Value = conditions\n\t} else {\n\t\tc.Value = aux.Value","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/repository/retriever/milvus/filter.go#L249-L285","documentation":"The public filter type's UnmarshalJSON parses AND/OR conditions expecting their Value to arrive as a JSON array of condition objects. It returns this error when the decoded Value is not []any — e.g. a scalar, object, or string was supplied for a logical operator.","triggerScenarios":"Unmarshaling JSON where \"operator\" is AND/OR but \"value\" is not an array (a single condition object, null, a string, or a number).","commonSituations":"Hand-written filter JSON wrapping a single condition without an array; an API client sending one sub-condition; schema changes where value became an object.","solutions":["Wrap the sub-condition in a JSON array for AND/OR: \"value\": [{...}]","Use an explicit AND/OR with one element if only one condition applies","Validate filter JSON shape before unmarshaling"],"exampleFix":"// before\n{\"operator\":\"AND\",\"value\":{\"field\":\"a\",\"operator\":\"EQUAL\",\"value\":1}}\n// after\n{\"operator\":\"AND\",\"value\":[{\"field\":\"a\",\"operator\":\"EQUAL\",\"value\":1}]}","handlingStrategy":"validation","validationCode":"var raw map[string]any\nif err := json.Unmarshal(data, &raw); err != nil { return err }\nif op, _ := raw[\"operator\"].(string); op == \"AND\" || op == \"OR\" {\n  if _, ok := raw[\"value\"].([]any); !ok {\n    return fmt.Errorf(\"logical operator %s requires value array\", op)\n  }\n}","typeGuard":"func logicalValueIsArray(raw map[string]any) bool {\n  op, _ := raw[\"operator\"].(string)\n  if op != \"AND\" && op != \"OR\" { return true }\n  _, ok := raw[\"value\"].([]any)\n  return ok\n}","tryCatchPattern":"var f Filter\nif err := json.Unmarshal(data, &f); err != nil {\n  if strings.Contains(err.Error(), \"requires an array of conditions\") {\n    return nil, fmt.Errorf(\"malformed logical node in filter JSON: %w\", err)\n  }\n  return nil, err\n}","preventionTips":["Always emit AND/OR sub-conditions as JSON arrays","Document the filter JSON schema for API clients","Pre-validate payloads against the schema before unmarshal"],"tags":["milvus","json","unmarshal"],"backgroundTag":"json-shape-mismatch","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}