usememos/memos · error
comprehension loop step must have two arguments
Error message
comprehension loop step must have two arguments
What it means
For exists()/all(), extractPredicate expects the loop step call (_||_ or _&&_) to have exactly two arguments and reads the predicate from Args[1]. A call with any other arity fails here.
Source
Thrown at internal/filter/parser.go:894
func extractPredicate(comp *exprv1.Expr_Comprehension, _ Schema) (PredicateExpr, error) {
// The loop step is: @result || predicate(t) for exists
// or: @result && predicate(t) for all
step := comp.LoopStep.GetCallExpr()
if step == nil {
return nil, errors.New("comprehension loop step must be a call expression")
}
// exists/all: accu || predicate / accu && predicate -> predicate is arg[1].
// exists_one: predicate ? accu + 1 : accu -> predicate is arg[0].
var predicateExpr *exprv1.Expr
if step.Function == "_?_:_" {
if len(step.Args) != 3 {
return nil, errors.New("exists_one loop step must have three arguments")
}
predicateExpr = step.Args[0]
} else {
if len(step.Args) != 2 {
return nil, errors.New("comprehension loop step must have two arguments")
}
predicateExpr = step.Args[1]
}
predicateCall := predicateExpr.GetCallExpr()
if predicateCall == nil {
return nil, errors.New("comprehension predicate must be a function call")
}
// Handle different predicate functions
switch predicateCall.Function {
case "_==_":
return buildEqualsPredicate(predicateCall, comp.IterVar)
case "startsWith":
return buildStartsWithPredicate(predicateCall, comp.IterVar)
case "endsWith":
return buildEndsWithPredicate(predicateCall, comp.IterVar)
case "contains":
return buildContainsPredicate(predicateCall, comp.IterVar)View on GitHub (pinned to 14d757ce1f)
Solutions
- Use the textual macro form tag.exists(t, predicate) / tag.all(t, predicate)
- Emit the canonical two-arg loop step accu || predicate when constructing ASTs manually
Defensive patterns
Strategy: try-catch
Try / catch
if err := r.Render(cond); err != nil {
if strings.Contains(err.Error(), "loop step must have two arguments") {
return errors.New("exists/all loop step malformed; use textual macro syntax")
}
return err
} Prevention
- Use textual exists()/all() forms
- Keep loop steps as canonical accu OP predicate two-arg calls
When it happens
Trigger: Programmatically built exists/all comprehension where the logical-operator call has fewer or more than 2 args; not reachable from standard textual macro expansion, which always produces accu OP predicate.
Common situations: Custom AST construction; partially-applied or rewritten loop steps from macro transforms.
Related errors
- comprehension accumulator must be initialized with a constan
- unsupported comprehension type (supported: exists, all, exis
- comprehension loop step must be a call expression
- exists_one loop step must have three arguments
- comprehension predicate must be a function call
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/e00170a22f8b4f0a.
Report an issue: GitHub.