usememos/memos · error
expression is not a literal
Error message
expression is not a literal
What it means
getConstValue requires the expression to be a constant literal (exprv1.Expr_ConstExpr) and unwraps string, int, uint, double, and bool kinds. Any non-literal — identifier, call, list — fails here; it typically surfaces wrapped as 'only supports literal arguments' from contains/matches/timestamp/duration validators.
Source
Thrown at internal/filter/parser.go:468
return CompareLte, nil
case "_>=_":
return CompareGte, nil
default:
return "", errors.Errorf("unsupported comparison operator %q", fn)
}
}
func getIdentName(expr *exprv1.Expr) (string, error) {
if ident := expr.GetIdentExpr(); ident != nil {
return ident.GetName(), nil
}
return "", errors.New("expression is not an identifier")
}
func getConstValue(expr *exprv1.Expr) (interface{}, error) {
v, ok := expr.ExprKind.(*exprv1.Expr_ConstExpr)
if !ok {
return nil, errors.New("expression is not a literal")
}
switch x := v.ConstExpr.ConstantKind.(type) {
case *exprv1.Constant_StringValue:
return v.ConstExpr.GetStringValue(), nil
case *exprv1.Constant_Int64Value:
return v.ConstExpr.GetInt64Value(), nil
case *exprv1.Constant_Uint64Value:
return int64(v.ConstExpr.GetUint64Value()), nil
case *exprv1.Constant_DoubleValue:
return v.ConstExpr.GetDoubleValue(), nil
case *exprv1.Constant_BoolValue:
return v.ConstExpr.GetBoolValue(), nil
case *exprv1.Constant_NullValue:
return nil, nil
default:
return nil, errors.Errorf("unsupported constant %T", x)
}
}View on GitHub (pinned to 14d757ce1f)
Solutions
- Replace the argument with a literal constant
- For field-to-field comparison use the == operator directly, not a function argument
- Fold arithmetic yourself and inline the resulting number/string
Example fix
// before
content.contains(tag)
// after
content.contains("work") Defensive patterns
Strategy: type-guard
Validate before calling
// Go (AST level): only pass ConstExpr nodes where literals are required
if arg.GetConstExpr() == nil {
return errors.New("argument must be a constant literal")
} Type guard
func isLiteral(e *exprv1.Expr) bool { return e.GetConstExpr() != nil } Prevention
- Treat function arguments as literal-only by design
- Use operators (==) for field-to-field comparisons
- Inline computed constants before building the filter
When it happens
Trigger: content.contains(tag) (identifier argument), timestamp(created_ts) (field argument), or duration(30 * 24) where the argument is an expression rather than a single literal.
Common situations: Trying to compare two fields via a function argument, or passing computed values where the DSL only accepts literals — the filter compiler intentionally forbids non-constant arguments so predicates can be compiled to SQL.
Related errors
- filter must evaluate to a boolean value
- unsupported top-level expression
- logical AND expects two arguments
- logical OR expects two arguments
- logical NOT expects one argument
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/031fff511b662fe3.
Report an issue: GitHub.