litedb-org/LiteDB · error · NotSupportedException

Expression {expr} can't return null value

Error message

Expression {expr} can't return null value

What it means

Thrown by the private Evaluate helper when validTypes are specified (one or more expected types passed) and the expression evaluates to null. Evaluate is used to compile-and-invoke sub-expressions that must produce a concrete value (e.g., array index values, method arguments). A null result with type constraints is rejected because the downstream BsonExpression cannot represent a typed null for those positions.

Source

Thrown at LiteDB/Client/Mapper/Linq/LinqExpressionVisitor.cs:731

            object value = null;

            if (expr.NodeType == ExpressionType.Constant)
            {
                var constant = (ConstantExpression)expr;

                value = constant.Value;
            }
            else
            {
                var func = Expression.Lambda(expr).Compile();

                value = func.DynamicInvoke();
            }

            // do some type validation to be ease to debug
            if (validTypes.Length > 0 && value == null)
            {
                throw new NotSupportedException($"Expression {expr} can't return null value");
            }

            if (validTypes.Length > 0 && validTypes.Any(x => x == value.GetType()) == false)
            {
                throw new NotSupportedException($"Expression {expr} must return on of this types: {string.Join(", ", validTypes.Select(x => $"`{x.Name}`"))}");
            }

            return value;
        }

        /// <summary>
        /// Tries to visit `new BsonRefId&lt;T&gt;(id)` within a member init expression.
        /// This is only resolved for properties marked as DbRef.
        /// </summary>
        private bool TryVisitDbRefIdExpression(Expression node, MemberMapper memberMapper, bool isInList = false)
        {
            if (!memberMapper.IsDbRef)
            {

View on GitHub (pinned to f906a5f850)

Solutions

  1. Null-check the variable before building the LINQ expression and throw or skip the query.
  2. Provide a non-null default value before the variable is captured in the expression.
  3. Ensure closure variables used as evaluated arguments (indices, method params) are always initialized.

Example fix

// before
string key = null;
var results = col.Find(x => x.Data[key] != null);
// key is null -> Evaluate throws

// after
if (key == null) throw new ArgumentNullException(nameof(key));
var results = col.Find(x => x.Data[key] != null);
Defensive patterns

Strategy: validation

Validate before calling

// Null-check closure variables before building the query expression
string key = GetKey();
if (key == null) throw new ArgumentNullException(nameof(key));
col.Find(x => x.Data[key] != null);

Type guard

// Guard against null values in evaluated expression arguments
static void EnsureNotNull<T>(T value, string name) where T : class
{
    if (value == null) throw new ArgumentNullException(name);
}

Try / catch

try
{
    var results = col.Find(x => x.Data[key] != null);
}
catch (NotSupportedException ex) when (ex.Message.Contains("can't return null value"))
{
    throw new ArgumentNullException(nameof(key), "Query argument cannot be null.", ex);
}

Prevention

When it happens

Trigger: An evaluated sub-expression returns null where Evaluate was called with validTypes. For example, a closure variable used as an array index or method argument is null: x => x.Items[idx] where idx is a null variable, or Evaluate(expr, typeof(int)) where expr evaluates to null.

Common situations: Passing a null closure variable into a query expression that gets evaluated (index access, method arguments). A nullable variable that was never assigned being captured in the expression tree. Database-first scenarios where caller code didn't null-check a parameter before building the query.

Related errors


AI-assisted analysis of litedb-org/LiteDB@f906a5f850 (2026-08-13). Data as JSON: /api/errors/49c9f5802efb0576. Report an issue: GitHub.