litedb-org/LiteDB · error · ArgumentException

Extend expression must return a document. Eg: `col.UpdateMan

Error message

Extend expression must return a document. Eg: `col.UpdateMany('{ Name: UPPER(Name) }', 'Age > 10')`

What it means

ArgumentException thrown by the string/transform overload of UpdateMany when the transform BsonExpression does not evaluate to a Document. UpdateMany(transform, predicate) replaces each matching document with the result of transform, which must be a Bson document literal/expression (e.g. '{ Name: UPPER($.Name), Age }'); any other expression type (scalar, array) is rejected because there is no document to write back.

Source

Thrown at LiteDB/Client/Database/Collections/Update.cs:62

        public int Update(IEnumerable<T> entities)
        {
            if (entities == null) throw new ArgumentNullException(nameof(entities));

            return _engine.Update(_collection, entities.Select(x => _mapper.ToDocument(x)));
        }

        /// <summary>
        /// Update many documents based on transform expression. This expression must return a new document that will be replaced over current document (according with predicate).
        /// Eg: col.UpdateMany("{ Name: UPPER($.Name), Age }", "_id > 0")
        /// </summary>
        public int UpdateMany(BsonExpression transform, BsonExpression predicate)
        {
            if (transform == null) throw new ArgumentNullException(nameof(transform));
            if (predicate == null) throw new ArgumentNullException(nameof(predicate));

            if (transform.Type != BsonExpressionType.Document)
            {
                throw new ArgumentException("Extend expression must return a document. Eg: `col.UpdateMany('{ Name: UPPER(Name) }', 'Age > 10')`");
            }

            return _engine.UpdateMany(_collection, transform, predicate);
        }

        /// <summary>
        /// Update many document based on merge current document with extend expression. Use your class with initializers. 
        /// Eg: col.UpdateMany(x => new Customer { Name = x.Name.ToUpper(), Salary: 100 }, x => x.Name == "John")
        /// </summary>
        public int UpdateMany(Expression<Func<T, T>> extend, Expression<Func<T, bool>> predicate)
        {
            if (extend == null) throw new ArgumentNullException(nameof(extend));
            if (predicate == null) throw new ArgumentNullException(nameof(predicate));

            var ext = _mapper.GetExpression(extend);
            var pred = _mapper.GetExpression(predicate);

            if (ext.Type != BsonExpressionType.Document)

View on GitHub (pinned to f906a5f850)

Solutions

  1. Make the transform a document expression: collection.UpdateMany("{ Name: UPPER($.Name) }", "_id > 0").
  2. Double-check argument order: transform first, predicate second.
  3. If you only want to set one field, still wrap it in a document literal.

Example fix

// before
collection.UpdateMany("UPPER($.Name)", "_id > 0");

// after
collection.UpdateMany("{ Name: UPPER($.Name) }", "_id > 0");
Defensive patterns

Strategy: validation

Validate before calling

// Validate the transform resolves to a document before calling UpdateMany
var transform = BsonExpression.Create("{ Name: UPPER($.Name) }");
if (transform.Type != BsonExpressionType.Document)
{
    throw new InvalidOperationException("UpdateMany transform must be a document expression.");
}
collection.UpdateMany(transform, BsonExpression.Create("_id > 0"));

Type guard

static bool IsDocumentExpression(BsonExpression expr) => expr?.Type == BsonExpressionType.Document;

Try / catch

try
{
    collection.UpdateMany(transform, predicate);
}
catch (ArgumentException ex) when (ex.Message.Contains("must return a document"))
{
    logger.LogError("UpdateMany transform must be a {{ ... }} document expression.");
    throw;
}

Prevention

When it happens

Trigger: Calling collection.UpdateMany("UPPER($.Name)", ...) where the transform is a scalar expression instead of a document; passing a predicate string into the transform argument by mistake; building a transform that resolves to a path or array.

Common situations: Confusing the transform (must yield a new document) with the predicate (a boolean filter); writing a transform expression that returns a single value rather than a { ... } document; argument order swap.

Related errors


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