{"record":{"id":"dda3cdb1fa4d5991","repo":"usememos/memos","slug":"logical-or-expects-two-arguments","errorCode":null,"errorMessage":"logical OR expects two arguments","messagePattern":"logical OR expects two arguments","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/filter/parser.go","lineNumber":69,"sourceCode":"\t\tif len(call.Args) != 2 {\n\t\t\treturn nil, errors.New(\"logical AND expects two arguments\")\n\t\t}\n\t\tleft, err := buildCondition(call.Args[0], pc)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tright, err := buildCondition(call.Args[1], pc)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &LogicalCondition{\n\t\t\tOperator: LogicalAnd,\n\t\t\tLeft:     left,\n\t\t\tRight:    right,\n\t\t}, nil\n\tcase \"_||_\":\n\t\tif len(call.Args) != 2 {\n\t\t\treturn nil, errors.New(\"logical OR expects two arguments\")\n\t\t}\n\t\tleft, err := buildCondition(call.Args[0], pc)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tright, err := buildCondition(call.Args[1], pc)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &LogicalCondition{\n\t\t\tOperator: LogicalOr,\n\t\t\tLeft:     left,\n\t\t\tRight:    right,\n\t\t}, nil\n\tcase \"!_\":\n\t\tif len(call.Args) != 1 {\n\t\t\treturn nil, errors.New(\"logical NOT expects one argument\")\n\t\t}","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/internal/filter/parser.go#L51-L87","documentation":"Returned by buildCallCondition for the \"_||_\" (logical OR) function when the call's argument count is not exactly 2. Like the AND twin, user-written CEL always yields binary ||, so this fires only from unusual AST shapes or macro desugaring.","triggerScenarios":"An Expr_Call tagged _||_ with arity != 2 in the parsed expression — e.g., from programmatic AST construction or a CEL macro that expands to OR over multiple args.","commonSituations":"Programmatic filter generation; edge-case macro expansions; effectively never from normal hand-written filters.","solutions":["Rewrite the || chain in explicit binary form with parentheses.","When constructing ASTs directly, emit _||_ calls with exactly two arguments.","Report as an engine bug if triggered by a plain filter."],"exampleFix":"# before\n(a || b || c)\n\n# after\n((a || b) || c)","handlingStrategy":"validation","validationCode":"// Go — emit binary OR chains when generating\nfunc orPair(l, r string) string { return fmt.Sprintf(\"(%s || %s)\", l, r) }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"logical OR expects two arguments\") {\n  return errors.Wrap(err, \"internal filter AST inconsistency; report with the filter text\")\n}","preventionTips":["Parenthesize every generated || chain.","Test generated filters against the real engine before shipping.","Treat arity errors from hand-written filters as bugs, not user errors."],"tags":["cel","filter","parser","logical-or","go"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}