usememos/memos · error

unsupported top-level expression

Error message

unsupported top-level expression

What it means

Returned by buildCondition's default branch when the top-level (or nested) AST node kind is a CallExpr, ConstExpr, IdentExpr, or Comprehension that was not matched — practically, an expression shape the condition builder does not translate. It marks the boundary of the supported CEL subset (logic ops, comparisons, in, text matches, comprehensions, boolean idents/constants).

Source

Thrown at internal/filter/parser.go:44

		}
		if v, ok := val.(bool); ok {
			return &ConstantCondition{Value: v}, nil
		}
		return nil, errors.New("filter must evaluate to a boolean value")
	case *exprv1.Expr_IdentExpr:
		name := v.IdentExpr.GetName()
		field, ok := pc.schema.Field(name)
		if !ok {
			return nil, errors.Errorf("unknown identifier %q", name)
		}
		if field.Type != FieldTypeBool {
			return nil, errors.Errorf("identifier %q is not boolean", name)
		}
		return &FieldPredicateCondition{Field: name}, nil
	case *exprv1.Expr_ComprehensionExpr:
		return buildComprehensionCondition(v.ComprehensionExpr, pc.schema)
	default:
		return nil, errors.New("unsupported top-level expression")
	}
}

func buildCallCondition(call *exprv1.Expr_Call, pc parseContext) (Condition, error) {
	switch call.Function {
	case "_&&_":
		if len(call.Args) != 2 {
			return nil, errors.New("logical AND expects two arguments")
		}
		left, err := buildCondition(call.Args[0], pc)
		if err != nil {
			return nil, err
		}
		right, err := buildCondition(call.Args[1], pc)
		if err != nil {
			return nil, err
		}
		return &LogicalCondition{

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Rewrite the filter using supported constructs: field comparisons, &&/||/!, in, contains, and macro comprehensions.
  2. Check the documented filter grammar/schema for the resource you are filtering.
  3. Simplify to nested boolean comparisons of the same intent.

Example fix

# before (unsupported shape)
[tag in ["a","b"] ? true : false]

# after
tag in ["a", "b"]
Defensive patterns

Strategy: validation

Validate before calling

// Go — restrict input to the supported grammar before compiling
var allowed = regexp.MustCompile(`^[a-zA-Z0-9_.()\s\[\]",!=<>@&|!'-]+$`)
if !allowed.MatchString(filter) {
  return errors.New("filter uses unsupported syntax")
}
_, err := engine.Compile(ctx, filter)

Try / catch

if err != nil && strings.Contains(err.Error(), "unsupported top-level expression") {
  return status.Errorf(codes.InvalidArgument, "unsupported filter syntax; use comparisons, in, contains, and logical operators")
}

Prevention

When it happens

Trigger: A filter whose root is a list/map literal, a ternary result of non-supported form, or any macro/expression kind outside the handled ExprKind cases. CEL's env may accept it syntactically while the Memos condition builder refuses to compile it to a Condition.

Common situations: Power users writing CEL beyond the supported subset (list literals, index expressions); filters written against a different CEL schema; engine version gaps after new syntax was allowed by env.Compile but not yet mapped in the parser.

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/9fbe6f8acb43076b. Report an issue: GitHub.