litedb-org/LiteDB · error · LiteException

0

0

Error message

Expression `{expression.Source}` must return a enumerable expression

What it means

LiteException (code 0) thrown by LiteCollection.GetIndexExpression when building a multi-key index from a LINQ selector. The selector's return type K is enumerable (e.g. IEnumerable/Array), the expression resolved to a scalar value, and it is not a simple path expression, so LiteDB cannot auto-convert it to the '$.Field[*]' multi-key form. Only simple member-path selectors like x => x.Phones get auto-expanded; computed or transformed enumerables are rejected.

Source

Thrown at LiteDB/Client/Database/Collections/Index.cs:145

        /// <summary>
        /// Get index expression based on LINQ expression. Convert IEnumerable in MultiKey indexes
        /// </summary>
        private BsonExpression GetIndexExpression<K>(Expression<Func<T, K>> keySelector, bool convertEnumerableToMultiKey = true)
        {
            var expression = _mapper.GetIndexExpression(keySelector);

            if (convertEnumerableToMultiKey && typeof(K).IsEnumerable() && expression.IsScalar == true)
            {
                if (expression.Type == BsonExpressionType.Path)
                {
                    // convert LINQ expression that returns an IEnumerable but expression returns a single value
                    // `x => x.Phones` --> `$.Phones[*]`
                    // works only if exression is a simple path
                    expression = expression.Source + "[*]";
                }
                else
                {
                    throw new LiteException(0, $"Expression `{expression.Source}` must return a enumerable expression");
                }
            }

            return expression;
        }

        /// <summary>
        /// Drop index and release slot for another index
        /// </summary>
        public bool DropIndex(string name)
        {
            return _engine.DropIndex(_collection, name);
        }
    }
}

View on GitHub (pinned to f906a5f850)

Solutions

  1. Index a simple stored enumerable field: EnsureIndex(x => x.Phones) so it rewrites to $.Phones[*].
  2. If you must index a projection, materialize it into a stored field on the document and index that field.
  3. Use the string overload EnsureIndex("name", "$.Phones[*]") to express the multi-key path directly.

Example fix

// before
db.GetCollection<User>().EnsureIndex(x => x.Phones.Select(p => p.Number));

// after
db.GetCollection<User>().EnsureIndex(x => x.PhoneNumbers); // stored List<string> field
// or
db.GetCollection<User>().EnsureIndex("phones", "$.Phones[*].Number");
Defensive patterns

Strategy: validation

Validate before calling

// Validate the selector is a simple member path before indexing
Expression<Func<T, IEnumerable<TItem>>> sel = x => x.Phones; // simple path only
// Or use the string overload to be explicit:
collection.EnsureIndex("phones", "$.Phones[*]");

Type guard

static bool IsSimpleMemberPath<T, K>(Expression<Func<T, K>> selector)
    => selector.Body is MemberExpression;
// Usage: only call multi-key EnsureIndex when IsSimpleMemberPath returns true; otherwise index a stored field.

Try / catch

try
{
    collection.EnsureIndex(x => x.Phones);
}
catch (LiteException ex) when (ex.Message.Contains("must return a enumerable expression"))
{
    // fall back to indexing a stored, simple enumerable field
    logger.LogWarning("Index selector was not a simple path; index skipped.");
}

Prevention

When it happens

Trigger: Calling EnsureIndex with a LINQ selector whose type K is enumerable but whose body is not a plain member access, e.g. EnsureIndex(x => x.Phones.Select(p => p.Number)) or EnsureIndex(x => x.Tags.Where(...)). The mapper produced a scalar BsonExpression, and because it is not a Path, the [*] rewrite is refused.

Common situations: Indexing a computed/derived collection property; projecting inside the index selector instead of indexing a stored array field; entity with a getter-only computed enumerable that the mapper cannot represent as a path.

Related errors


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