usememos/memos · error
matches argument must be a string
Error message
matches argument must be a string
What it means
After arity checks, the matches() pattern must be a string literal. getConstValue returns the constant but the type switch only accepts string, so numeric, boolean, or identifier arguments fail with this error before a RegexCondition is built.
Source
Thrown at internal/filter/parser.go:370
}
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 matches()", targetName)
}
if len(call.Args) != 1 {
return nil, errors.New("matches expects exactly one argument")
}
value, err := getConstValue(call.Args[0])
if err != nil {
return nil, errors.Wrap(err, "matches only supports literal arguments")
}
pattern, ok := value.(string)
if !ok {
return nil, errors.New("matches argument must be a string")
}
return &RegexCondition{
Field: targetName,
Pattern: pattern,
}, nil
}
func buildValueExpr(expr *exprv1.Expr, pc parseContext) (ValueExpr, error) {
if identName, err := getIdentName(expr); err == nil {
// `now` is not a schema field; it folds to the frozen evaluation time.
if identName == "now" {
return &LiteralValue{Value: pc.now.Unix()}, nil
}
if _, ok := pc.schema.Field(identName); !ok {
return nil, errors.Errorf("unknown identifier %q", identName)
}
return &FieldRef{Name: identName}, nil
}View on GitHub (pinned to 14d757ce1f)
Solutions
- Quote the pattern: content.matches("^[A-Z]")
- Escape the pattern when embedding it from code (strconv.Quote) to keep it one literal
- Remember only literal arguments are supported; there is no dynamic pattern binding
Example fix
// before
content.matches(123)
// after
content.matches("123") Defensive patterns
Strategy: validation
Validate before calling
// Ensure the pattern slot holds a quoted literal before sending
const ok = /^"(?:[^"\\]|\\.)*"$/.test(patternToken);
if (!ok) throw new Error('matches pattern must be a quoted string literal'); Type guard
const isQuotedPattern = (p: string): boolean => /^"(?:[^"\\]|\\.)*"$/.test(p);
Prevention
- Embed regex patterns via JSON.stringify to guarantee literal quoting
- Do not reference identifiers or numbers as patterns
- Test pattern escaping (backslashes) in generated filters
When it happens
Trigger: content.matches(123), content.matches(someVar), or any matches() call whose sole argument is not a quoted string literal.
Common situations: Interpolating a precompiled pattern object or unquoted variable into the filter string; forgetting that the filter DSL has no variable binding besides schema fields.
Related errors
- text match argument must be a string
- matches requires a target
- matches expects exactly one argument
- timestamp() argument must be an RFC3339 string or epoch int
- duration() argument must be a string
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/19bbde66be3b0669.
Report an issue: GitHub.