usememos/memos · error
set operations require a list literal as the second argument
Error message
set operations require a list literal as the second argument
What it means
Set operations (in / not-in style membership over JSON list fields) require the second argument to be a CEL list literal, e.g. tag in ["work", "urgent"]. The parser inspects call.Args[1].GetListExpr(); when it is nil (an identifier, call, or string), compilation fails because only literal lists can be translated to SQL.
Source
Thrown at internal/filter/parser.go:726
if len(call.Args) != 2 {
return nil, errors.Errorf("%s expects two arguments", call.Function)
}
fieldName, err := getIdentName(call.Args[0])
if err != nil {
return nil, errors.Wrap(err, "set operations require a list field as the first argument")
}
field, ok := pc.schema.Field(fieldName)
if !ok {
return nil, errors.Errorf("unknown identifier %q", fieldName)
}
if field.Kind != FieldKindJSONList {
return nil, errors.Errorf("set operations require a list field, got %q", fieldName)
}
listExpr := call.Args[1].GetListExpr()
if listExpr == nil {
return nil, errors.New("set operations require a list literal as the second argument")
}
values := make([]string, 0, len(listExpr.Elements))
for _, el := range listExpr.Elements {
v, err := getConstValue(el)
if err != nil {
return nil, errors.Wrap(err, "set operations only support literal string elements")
}
s, ok := v.(string)
if !ok {
return nil, errors.New("set operations require string elements")
}
values = append(values, s)
}
membership := func(s string) Condition {
return &ElementInCondition{Element: &LiteralValue{Value: s}, Field: fieldName}
}
sizeEquals := func(n int) Condition {View on GitHub (pinned to 14d757ce1f)
Solutions
- Wrap the values in a list literal: tag in ["work", "urgent"]
- For a single value, still use a one-element list: tag in ["work"]
- Build the list literal by joining pre-quoted strings when generating filters from code
Example fix
// before tag in "work" // after tag in ["work"]
Defensive patterns
Strategy: validation
Validate before calling
// TS: build a safe membership filter from a string array
const buildIn = (field: string, values: string[]) =>
`${field} in [${values.map(v => JSON.stringify(String(v))).join(', ')}]`;
if (values.length === 0) throw new Error('membership list cannot be empty'); Type guard
const isStringArray = (v: unknown): v is string[] => Array.isArray(v) && v.every(x => typeof x === 'string');
Prevention
- Always wrap membership values in [ ... ] list literal syntax
- JSON-encode each element when generating filters programmatically
- Never pass a field name or bare string as the in operand
When it happens
Trigger: tag in "work" (bare string instead of list), tag in tag (field on both sides), or tag in someList where someList is an unsupported function result.
Common situations: Treating in like SQL's IN with a comma string ("work,urgent"); attempting list-to-list containment between two fields; variable substitution that emits a non-list value.
Related errors
- size() expects one argument
- set operations require string elements
- comprehension range must be a field identifier
- filter expression is empty
- filter must evaluate to a boolean value
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/31305af924311d3e.
Report an issue: GitHub.