{"record":{"id":"e449e08cb4a3fe1b","repo":"usememos/memos","slug":"invalid-use-of-in-operator","errorCode":null,"errorMessage":"invalid use of in operator","messagePattern":"invalid use of in operator","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/filter/parser.go","lineNumber":308,"sourceCode":"\t\t}\n\t}\n\n\t// Handle \"value in identifier\" syntax.\n\tif identName, err := getIdentName(call.Args[1]); err == nil {\n\t\tif _, ok := pc.schema.Field(identName); !ok {\n\t\t\treturn nil, errors.Errorf(\"unknown identifier %q\", identName)\n\t\t}\n\t\telement, err := buildValueExpr(call.Args[0], pc)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &ElementInCondition{\n\t\t\tElement: element,\n\t\t\tField:   identName,\n\t\t}, nil\n\t}\n\n\treturn nil, errors.New(\"invalid use of in operator\")\n}\n\nfunc buildTextMatchCondition(call *exprv1.Expr_Call, schema Schema, mode TextMatchMode) (Condition, error) {\n\tif call.Target == nil {\n\t\treturn nil, errors.New(\"text match requires a target\")\n\t}\n\ttargetName, err := getIdentName(call.Target)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfield, ok := schema.Field(targetName)\n\tif !ok {\n\t\treturn nil, errors.Errorf(\"unknown identifier %q\", targetName)\n\t}\n\tif !field.SupportsContains {\n\t\treturn nil, errors.Errorf(\"identifier %q does not support text matching\", targetName)\n\t}","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/internal/filter/parser.go#L290-L326","documentation":"Returned by buildInCondition's fallthrough when the @in call has 2 args but its shape matches neither supported form: 'identifier in list' nor 'value in identifier'. Both branches require Args[0] (or Args[1]) to resolve to a schema-known identifier; anything else (e.g., two list literals, or an identifier not in the schema and not a valid alias) ends here.","triggerScenarios":"Filters like '[1,2] in [1,2]' (list in list) or 'unknownField in [...]' where the left side is neither a resolvable identifier nor paired with one on the right; also right-side non-identifier targets that earlier checks reject, leaving no valid branch.","commonSituations":"Typos in field names inside in-expressions; copied filters against a different schema where the field does not exist; over-clever expressions with computed values on both sides.","solutions":["Put a known field on one side: tag in [\"a\"] or \"a\" in tag_list — check the schema for the exact identifier name.","Fix typos in the identifier (unknown ones fail schema.Field lookup earlier with 'unknown identifier').","Avoid list-in-list or expression-in-expression forms; they are unsupported."],"exampleFix":"# before\n[tags] in [[\"a\"]]\n\n# after\ntag in [\"a\"]","handlingStrategy":"validation","validationCode":"// Go — verify the identifier exists in the schema before compiling user filters\nfor _, id := range extractIdentifiers(filter) {\n  if _, ok := schema.Field(id); !ok {\n    return errors.Errorf(\"unknown identifier %q in filter\", id)\n  }\n}\n_, err := engine.Compile(ctx, filter)","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"invalid use of in operator\") {\n  return status.Errorf(codes.InvalidArgument, \"use '<field> in [values]' or '<value> in <field>'\")\n}","preventionTips":["Always place a known schema field on one side of 'in'.","Autocomplete field names in the filter UI to avoid typos.","Reject list-in-list forms early with a helpful message."],"tags":["cel","filter","parser","in-operator","validation","go"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}