usememos/memos · error
filter expression is empty
Error message
filter expression is empty
What it means
Returned by Engine.Compile (internal/filter/engine.go) when the CEL filter string is empty or whitespace-only after TrimSpace. An empty filter has no condition tree to execute, so compilation is rejected up front rather than producing a nil program.
Source
Thrown at internal/filter/engine.go:50
nowFunc: time.Now,
}, nil
}
// Program stores a compiled filter condition.
type Program struct {
schema Schema
condition Condition
}
// ConditionTree exposes the underlying condition tree.
func (p *Program) ConditionTree() Condition {
return p.condition
}
// Compile parses the filter string into an executable program.
func (e *Engine) Compile(_ context.Context, filter string) (*Program, error) {
if strings.TrimSpace(filter) == "" {
return nil, errors.New("filter expression is empty")
}
ast, issues := e.env.Compile(filter)
if issues != nil && issues.Err() != nil {
return nil, errors.Wrap(issues.Err(), "failed to compile filter")
}
parsed, err := cel.AstToParsedExpr(ast)
if err != nil {
return nil, errors.Wrap(err, "failed to convert AST")
}
cond, err := buildCondition(parsed.GetExpr(), parseContext{schema: e.schema, now: e.nowFunc()})
if err != nil {
return nil, err
}
return &Program{
schema: e.schema,View on GitHub (pinned to 14d757ce1f)
Solutions
- Omit the filter field entirely (proto optional/empty string means 'no filter') when you want all results.
- Trim input upstream and treat empty as 'match everything' instead of compiling it.
- Provide at least one boolean expression, e.g., "pinned == true".
Example fix
// before
prog, err := engine.Compile(ctx, strings.TrimSpace(filter)) // "" -> error
// after
if strings.TrimSpace(filter) == "" {
return listAll(ctx) // no filter means match everything
}
prog, err := engine.Compile(ctx, filter) Defensive patterns
Strategy: validation
Validate before calling
// Go — treat empty as 'no filter' before compiling
trimmed := strings.TrimSpace(filter)
if trimmed == "" {
return engine.ListAll(ctx) // or return an empty Program that matches everything
}
prog, err := engine.Compile(ctx, trimmed) Try / catch
prog, err := engine.Compile(ctx, filter)
if err != nil {
if strings.Contains(err.Error(), "filter expression is empty") {
return status.Errorf(codes.InvalidArgument, "filter must not be empty; omit the field to list all")
}
return err
} Prevention
- Trim user input and branch on empty before calling Compile.
- In proto/API clients, omit optional filter fields instead of sending "".
- Reject empty filters at save time for stored views.
When it happens
Trigger: Calling Engine.Compile with "", " ", or a value that trims to empty — e.g., a ListMemos request with filter unset-but-empty-string, a UI saved-search whose filter was cleared, or trimming user input before compile.
Common situations: Frontend sending filter: "" instead of omitting the field; saved views with cleared filters; scripts copying an example but leaving the filter blank.
Related errors
- filter must evaluate to a boolean value
- invalid use of in operator
- unsupported top-level expression
- logical AND expects two arguments
- logical OR expects two arguments
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/2ad132a03ee6522f.
Report an issue: GitHub.