{"record":{"id":"ebfaa6fe4acda383","repo":"Tencent/WeKnora","slug":"empty-logical-condition","errorCode":null,"errorMessage":"empty logical condition","messagePattern":"empty logical condition","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/repository/retriever/milvus/filter.go","lineNumber":132,"sourceCode":"\t\tif childRes == nil || childRes.exprStr == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif condResult == nil {\n\t\t\tcondResult = childRes\n\t\t\tcontinue\n\t\t}\n\n\t\tcondResult.exprStr = fmt.Sprintf(\n\t\t\t\"(%s) %s (%s)\",\n\t\t\tcondResult.exprStr,\n\t\t\tstrings.ToLower(cond.Operator),\n\t\t\tchildRes.exprStr,\n\t\t)\n\t\tmaps.Copy(condResult.params, childRes.params)\n\t}\n\n\tif condResult == nil {\n\t\treturn nil, fmt.Errorf(\"empty logical condition\")\n\t}\n\treturn condResult, nil\n}\n\nfunc (c *filter) convertCondition(\n\tcond *universalFilterCondition,\n\tcounter *int,\n) (*convertResult, error) {\n\tif cond == nil {\n\t\treturn nil, fmt.Errorf(\"milvus filter condition is nil\")\n\t}\n\tswitch cond.Operator {\n\tcase operatorEqual, operatorNotEqual, operatorGreaterThan,\n\t\toperatorGreaterThanOrEqual, operatorLessThan,\n\t\toperatorLessThanOrEqual, operatorLike, operatorNotLike:\n\t\treturn c.convertComparisonCondition(cond, counter)\n\tcase operatorAnd, operatorOr:\n\t\treturn c.convertLogicalCondition(cond, counter)","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/repository/retriever/milvus/filter.go#L114-L150","documentation":"convertLogicalCondition builds a Milvus boolean expression from an AND/OR condition's children. It returns this error when, after iterating over the condition's children, no convertResult was produced (e.g. the children array was empty), so there is no expression string to emit.","triggerScenarios":"Calling Convert with a logical (AND/OR) condition whose Value array is empty, or whose children all fail silently to produce a result.","commonSituations":"Deserializing a filter from JSON where \"value\": [] for an AND/OR node; programmatically building nested filters and appending no sub-conditions.","solutions":["Ensure AND/OR conditions contain at least one child condition in their Value array","Validate the filter before calling Convert, rejecting logical operators with empty condition arrays","Log the full condition tree to find the empty logical node"],"exampleFix":"// before\ncond := &UniversalFilterCondition{Operator: \"AND\", Value: []*UniversalFilterCondition{}}\nres, err := f.Convert(ctx, cond) // error: empty logical condition\n// after\ncond := &UniversalFilterCondition{Operator: \"AND\", Value: []*UniversalFilterCondition{\n  {Field: \"age\", Operator: \"GREATER_THAN\", Value: 18},\n}}\nres, err := f.Convert(ctx, cond)","handlingStrategy":"validation","validationCode":"func validLogical(c *UniversalFilterCondition) bool {\n  if c.Operator != \"AND\" && c.Operator != \"OR\" { return true }\n  conds, ok := c.Value.([]*UniversalFilterCondition)\n  return ok && len(conds) > 0\n}","typeGuard":"func isLogicalWithChildren(c *UniversalFilterCondition) bool {\n  conds, ok := c.Value.([]*UniversalFilterCondition)\n  return ok && len(conds) > 0\n}","tryCatchPattern":"res, err := f.Convert(ctx, cond)\nif err != nil {\n  if strings.Contains(err.Error(), \"empty logical condition\") {\n    return nil, fmt.Errorf(\"filter has an AND/OR node with no sub-conditions: %w\", err)\n  }\n  return nil, err\n}","preventionTips":["Never construct AND/OR conditions with an empty Value slice","Add a unit test covering empty logical nodes","Centralize filter construction in a builder that enforces >=1 child"],"tags":["milvus","filter","validation"],"backgroundTag":"empty-filter-condition","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}