{"record":{"id":"ad4940fe78a1af44","repo":"usememos/memos","slug":"comparison-expects-two-arguments","errorCode":null,"errorMessage":"comparison expects two arguments","messagePattern":"comparison expects two arguments","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/filter/parser.go","lineNumber":121,"sourceCode":"\tcase \"matches\":\n\t\treturn buildMatchesCondition(call, pc.schema)\n\tcase \"sets.contains\", \"sets.intersects\", \"sets.equivalent\":\n\t\treturn buildSetCondition(call, pc)\n\tdefault:\n\t\tval, ok, err := evaluateBool(call)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif ok {\n\t\t\treturn &ConstantCondition{Value: val}, nil\n\t\t}\n\t\treturn nil, errors.Errorf(\"unsupported call expression %q\", call.Function)\n\t}\n}\n\nfunc buildComparisonCondition(call *exprv1.Expr_Call, pc parseContext) (Condition, error) {\n\tif len(call.Args) != 2 {\n\t\treturn nil, errors.New(\"comparison expects two arguments\")\n\t}\n\top, err := toComparisonOperator(call.Function)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tleft, err := buildValueExpr(call.Args[0], pc)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tright, err := buildValueExpr(call.Args[1], pc)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// The renderer expects a field/function/accessor on the left. A folded\n\t// literal on the left (e.g. now.getMonth() == created_ts.getMonth()) swaps\n\t// operands; two literals fold to a constant outcome.","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/internal/filter/parser.go#L103-L139","documentation":"Returned by buildComparisonCondition (internal/filter/parser.go) when a comparison call (_==_, _!=_, _<_, _>_, _<=_, _>=_) does not carry exactly 2 arguments. Standard CEL comparisons are binary, so this indicates an unusual AST rather than ordinary user syntax.","triggerScenarios":"A parsed comparison Expr_Call with arity != 2 — possible via programmatic AST construction, macro desugaring edge cases, or corrupted parsed expressions; not from a normal hand-written comparison.","commonSituations":"Code that synthesizes filter ASTs; parser tests; effectively unreachable through the public Compile(string) path with well-formed input.","solutions":["Write comparisons in plain binary form: pinned == true, created_ts < 1234567890.","If constructing ASTs directly, always emit comparison calls with exactly two args.","Report as an engine bug if a hand-written filter triggers it."],"exampleFix":"# before (generated AST misuse)\n\n# after\npinned == true","handlingStrategy":"validation","validationCode":"// Go — always emit 'field <op> value' pairs when generating comparisons\nfunc cmp(field, op string, v any) string { return fmt.Sprintf(\"%s %s %v\", field, op, v) }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"comparison expects two arguments\") {\n  return errors.Wrap(err, \"internal filter AST inconsistency; report with the filter text\")\n}","preventionTips":["Generate comparisons as strict binary calls.","Smoke-compile generated filters in CI.","Keep values properly typed (quotes for strings, raw for numbers/bools)."],"tags":["cel","filter","parser","comparison","go"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}