{"record":{"id":"0372fc004623b87f","repo":"usememos/memos","slug":"unsupported-comprehension-type-supported-exists","errorCode":null,"errorMessage":"unsupported comprehension type (supported: exists, all, exists_one)","messagePattern":"unsupported comprehension type \\(supported: exists, all, exists_one\\)","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/filter/parser.go","lineNumber":872,"sourceCode":"\t\t}\n\t}\n\n\t// all() starts with true and uses AND (&&) in the loop step.\n\tif accuInit.GetBoolValue() {\n\t\tif step := comp.LoopStep.GetCallExpr(); step != nil && step.Function == \"_&&_\" {\n\t\t\treturn ComprehensionAll, nil\n\t\t}\n\t}\n\n\t// exists_one() starts at int(0) and increments via a conditional (predicate ?\n\t// accu + 1 : accu) in the loop step.\n\tif _, isInt := accuInit.GetConstantKind().(*exprv1.Constant_Int64Value); isInt {\n\t\tif step := comp.LoopStep.GetCallExpr(); step != nil && step.Function == \"_?_:_\" {\n\t\t\treturn ComprehensionExistsOne, nil\n\t\t}\n\t}\n\n\treturn \"\", errors.New(\"unsupported comprehension type (supported: exists, all, exists_one)\")\n}\n\n// extractPredicate extracts the predicate expression from the comprehension loop step.\nfunc extractPredicate(comp *exprv1.Expr_Comprehension, _ Schema) (PredicateExpr, error) {\n\t// The loop step is: @result || predicate(t) for exists\n\t//                or: @result && predicate(t) for all\n\tstep := comp.LoopStep.GetCallExpr()\n\tif step == nil {\n\t\treturn nil, errors.New(\"comprehension loop step must be a call expression\")\n\t}\n\n\t// exists/all: accu || predicate  /  accu && predicate  -> predicate is arg[1].\n\t// exists_one: predicate ? accu + 1 : accu               -> predicate is arg[0].\n\tvar predicateExpr *exprv1.Expr\n\tif step.Function == \"_?_:_\" {\n\t\tif len(step.Args) != 3 {\n\t\t\treturn nil, errors.New(\"exists_one loop step must have three arguments\")\n\t\t}","sourceCodeStart":854,"sourceCodeEnd":890,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/internal/filter/parser.go#L854-L890","documentation":"detectComprehensionKind recognized a comprehension but could not match it to any supported macro. The parser only supports exists() (accu=false + ||), all() (accu=true + &&), and exists_one() (accu=int 0 + ternary). Any other comprehension shape — map(), filter(), list macros, sum(), etc. — falls through to this error.","triggerScenarios":"CEL filter using an unsupported macro on a list field, e.g. tag.map(t, t.size()) , tag.filter(...), tag.sum(...) or exists_one written against a loop step the pattern matcher does not recognize (e.g. accu init is int but loop step is not _?_:_).","commonSituations":"Users familiar with full CEL try list transformations in the memo filter bar; API clients send filters copied from other CEL-based systems (Envoy, Firebase rules) that allow map/filter macros.","solutions":["Restrict list predicates to exists(), all(), or exists_one(), e.g. tag.exists(t, t.startsWith(\"work\"))","Replace map()/filter() intent with the supported predicate functions ==, startsWith, endsWith, contains inside exists/all"],"exampleFix":"// before\n`tag.map(t, t.upperAscii()).exists(t, t == \"WORK\")`\n\n// after\n`tag.exists(t, t == \"work\")`","handlingStrategy":"validation","validationCode":"var unsupportedMacros = regexp.MustCompile(`\\.\\s*(map|filter|sum|take|drop)\\s*\\(`)\n\nfunc validateFilter(expr string) error {\n    if unsupportedMacros.MatchString(expr) {\n        return errors.New(\"only exists/all/exists_one macros are supported\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := r.Render(cond); err != nil {\n    if strings.Contains(err.Error(), \"unsupported comprehension type\") {\n        return userErr(\"filter uses an unsupported list macro; use exists, all, or exists_one\")\n    }\n    return err\n}","preventionTips":["Document the supported macro whitelist (exists, all, exists_one) at the filter input UI","Test filter strings against the parser in CI when shipping new filter examples","Reject filters early at the API boundary instead of at SQL render time"],"tags":["cel","filter","parser","comprehension","unsupported-operation"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}