litedb-org/LiteDB · error · NotSupportedException
Expression {expr.ToString()} must be a lambda expression
Error message
Expression {expr.ToString()} must be a lambda expression What it means
Thrown by the LinqExpressionVisitor constructor when the expression passed is not a LambdaExpression. The visitor needs a lambda to extract its root parameter, which drives all downstream member-access resolution. Without a lambda there is no parameter context to translate against.
Source
Thrown at LiteDB/Client/Mapper/Linq/LinqExpressionVisitor.cs:60
private readonly BsonDocument _parameters = new BsonDocument();
private int _paramIndex = 0;
private Type _dbRefType = null;
private readonly StringBuilder _builder = new StringBuilder();
private readonly Stack<MemberExpression> _memberAccessNodes = new();
public LinqExpressionVisitor(BsonMapper mapper, Expression expr)
{
_mapper = mapper;
_expr = expr;
if (expr is LambdaExpression lambda)
{
_rootParameter = lambda.Parameters.First();
}
else
{
throw new NotSupportedException($"Expression {expr.ToString()} must be a lambda expression");
}
}
public BsonExpression Resolve(bool predicate)
{
this.Visit(_expr);
ENSURE(_memberAccessNodes.Count == 0, "Member access node stack must be empty when finish expression resolve");
var expression = _builder.ToString();
try
{
var e = BsonExpression.Create(expression, _parameters);
// if expression must return an predicate but expression result is Path/Parameter/Call add `= true`
if (predicate && (e.Type == BsonExpressionType.Path || e.Type == BsonExpressionType.Call || e.Type == BsonExpressionType.Parameter))
{View on GitHub (pinned to f906a5f850)
Solutions
- Always pass a lambda expression (x => x.Something) to the LINQ query APIs (Find, Query.Where, etc.).
- Do not construct LinqExpressionVisitor directly; use BsonMapper.GetExpression or GetIndexExpression.
- If subclassing BsonMapper, ensure any override that builds a LinqExpressionVisitor passes a lambda expression.
Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the expression is a lambda before passing to query APIs
static void EnsureLambda<T>(Expression<T> expr)
{
if (expr is not LambdaExpression)
throw new ArgumentException("Expression must be a lambda.", nameof(expr));
} Type guard
// Type guard: Expression<Func<T,K>> is always a lambda at the type level. // If building expressions dynamically: static bool IsLambdaExpression(Expression expr) => expr is LambdaExpression;
Try / catch
try
{
var bsonExpr = mapper.GetExpression<MyEntity, bool>(predicate);
}
catch (NotSupportedException ex) when (ex.Message.Contains("must be a lambda expression"))
{
throw new InvalidOperationException("Query predicate must be a lambda expression.", ex);
} Prevention
- Always use typed lambdas (Expression<Func<T,K>>) with GetExpression/GetIndexExpression.
- Never construct LinqExpressionVisitor directly with a raw Expression.
- If dynamically building expressions, wrap them in Expression.Lambda before use.
When it happens
Trigger: Constructing a LinqExpressionVisitor with an Expression that is not a LambdaExpression (e.g., a bare MemberExpression, ConstantExpression, or MethodCallExpression).
Common situations: Effectively unreachable from the public API surface: GetExpression<T,K> and GetIndexExpression<T,K> both accept Expression<Func<T,K>> which is always a lambda. Could surface if the visitor is instantiated via reflection or in a custom BsonMapper subclass that passes a raw non-lambda Expression.
Related errors
- 0
- Extend expression must return an anonymous class to be merge
- Operator not supported {nodeType}
- Extend expression must return a document. Eg: `col.UpdateMan
- Multiple OrderBy calls are not supported. Use ThenBy for add
AI-assisted analysis of litedb-org/LiteDB@f906a5f850 (2026-08-13).
Data as JSON: /api/errors/d0c114be380f4935.
Report an issue: GitHub.