usememos/memos · error
text match expects exactly one argument
Error message
text match expects exactly one argument
What it means
The CEL filter parser rejects a text-matching call (contains/endsWith/startsWith-style text match) whose argument count is not exactly one. internal/filter/parser.go builds a TextMatchCondition only for calls of the form field.textMatch(literal), and arity other than 1 has no valid SQL translation. This is a compile-time validation of the user-supplied filter string, not a runtime data error.
Source
Thrown at internal/filter/parser.go:328
func buildTextMatchCondition(call *exprv1.Expr_Call, schema Schema, mode TextMatchMode) (Condition, error) {
if call.Target == nil {
return nil, errors.New("text match requires a target")
}
targetName, err := getIdentName(call.Target)
if err != nil {
return nil, err
}
field, ok := schema.Field(targetName)
if !ok {
return nil, errors.Errorf("unknown identifier %q", targetName)
}
if !field.SupportsContains {
return nil, errors.Errorf("identifier %q does not support text matching", targetName)
}
if len(call.Args) != 1 {
return nil, errors.New("text match expects exactly one argument")
}
value, err := getConstValue(call.Args[0])
if err != nil {
return nil, errors.Wrap(err, "text match only supports literal arguments")
}
str, ok := value.(string)
if !ok {
return nil, errors.New("text match argument must be a string")
}
return &TextMatchCondition{
Field: targetName,
Mode: mode,
Value: str,
}, nil
}
func buildMatchesCondition(call *exprv1.Expr_Call, schema Schema) (Condition, error) {
if call.Target == nil {View on GitHub (pinned to 14d757ce1f)
Solutions
- Provide exactly one quoted string argument: content.contains("meeting")
- Remove any extra arguments; options like case sensitivity are not supported as extra args
- Validate the filter string with a CEL parse step before sending it to the API
Example fix
// before
content.contains()
// after
content.contains("meeting") Defensive patterns
Strategy: validation
Validate before calling
// Go: assert the contains/text-match call shape before submitting
import (
"fmt"
"strings"
)
func checkTextMatch(field, filter string) error {
if !strings.Contains(filter, field+".contains(") {
return nil
}
// crude arity check: content between the matching parens must be exactly one quoted literal
i := strings.Index(filter, field+".contains(") + len(field) + len(".contains(")
rest := filter[i:]
end := strings.Index(rest, ")")
arg := strings.TrimSpace(rest[:end])
if arg == "" {
return fmt.Errorf("contains() needs exactly one argument")
}
return nil
} Try / catch
err := filterExpr.Validate(parsedAst) // compile the filter first; surface parse errors to the user input form instead of failing the request later
Prevention
- Run filters through a CEL parse+compile dry-run before saving or executing them
- Show users the supported grammar (field.contains("literal")) next to the filter input
- Write unit tests for each accepted filter shape your product advertises
When it happens
Trigger: A filter expression like content.contains() (zero args) or content.contains("a", "b") (two args) sent to the memo list/filter API that accepts CEL filters. The parser reaches buildTextMatchCondition with len(call.Args) != 1 and returns the error before any SQL is generated.
Common situations: Hand-building filter strings in a script or client SDK and forgetting the argument, passing extra locale/option arguments copied from another API (e.g. JS String.prototype.includes habits), or a malformed concatenation that produces an empty argument.
Related errors
- filter must evaluate to a boolean value
- invalid use of in operator
- filter expression is empty
- unsupported top-level expression
- logical AND expects two arguments
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/59a44221b06569d1.
Report an issue: GitHub.