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
- Make the transform a document expression: collection.UpdateMany("{ Name: UPPER($.Name) }", "_id > 0").
- Double-check argument order: transform first, predicate second.
- 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
- Always wrap transform fields in a { ... } document literal.
- Keep argument order straight: transform first, predicate second.
- If setting a single field, still use a document literal with that one field.
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
- Extend expression must return an anonymous class to be merge
- 0
- Multiple OrderBy calls are not supported. Use ThenBy for add
- GROUP BY already defined in this query
- HAVING already defined in this query
AI-assisted analysis of litedb-org/LiteDB@f906a5f850 (2026-08-13).
Data as JSON: /api/errors/f9b8cc7c6dd06d2e.
Report an issue: GitHub.