{"record":{"id":"f9b8cc7c6dd06d2e","repo":"litedb-org/LiteDB","slug":"extend-expression-must-return-a-document-eg-col","errorCode":null,"errorMessage":"Extend expression must return a document. Eg: `col.UpdateMany('{ Name: UPPER(Name) }', 'Age > 10')`","messagePattern":"Extend expression must return a document\\. Eg: `col\\.UpdateMany\\('(.+?)', 'Age > 10'\\)`","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"LiteDB/Client/Database/Collections/Update.cs","lineNumber":62,"sourceCode":"        public int Update(IEnumerable<T> entities)\n        {\n            if (entities == null) throw new ArgumentNullException(nameof(entities));\n\n            return _engine.Update(_collection, entities.Select(x => _mapper.ToDocument(x)));\n        }\n\n        /// <summary>\n        /// Update many documents based on transform expression. This expression must return a new document that will be replaced over current document (according with predicate).\n        /// Eg: col.UpdateMany(\"{ Name: UPPER($.Name), Age }\", \"_id > 0\")\n        /// </summary>\n        public int UpdateMany(BsonExpression transform, BsonExpression predicate)\n        {\n            if (transform == null) throw new ArgumentNullException(nameof(transform));\n            if (predicate == null) throw new ArgumentNullException(nameof(predicate));\n\n            if (transform.Type != BsonExpressionType.Document)\n            {\n                throw new ArgumentException(\"Extend expression must return a document. Eg: `col.UpdateMany('{ Name: UPPER(Name) }', 'Age > 10')`\");\n            }\n\n            return _engine.UpdateMany(_collection, transform, predicate);\n        }\n\n        /// <summary>\n        /// Update many document based on merge current document with extend expression. Use your class with initializers. \n        /// Eg: col.UpdateMany(x => new Customer { Name = x.Name.ToUpper(), Salary: 100 }, x => x.Name == \"John\")\n        /// </summary>\n        public int UpdateMany(Expression<Func<T, T>> extend, Expression<Func<T, bool>> predicate)\n        {\n            if (extend == null) throw new ArgumentNullException(nameof(extend));\n            if (predicate == null) throw new ArgumentNullException(nameof(predicate));\n\n            var ext = _mapper.GetExpression(extend);\n            var pred = _mapper.GetExpression(predicate);\n\n            if (ext.Type != BsonExpressionType.Document)","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/litedb-org/LiteDB/blob/f906a5f850678719e39a39a006cb66dcae563cfa/LiteDB/Client/Database/Collections/Update.cs#L44-L80","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncollection.UpdateMany(\"UPPER($.Name)\", \"_id > 0\");\n\n// after\ncollection.UpdateMany(\"{ Name: UPPER($.Name) }\", \"_id > 0\");","handlingStrategy":"validation","validationCode":"// Validate the transform resolves to a document before calling UpdateMany\nvar transform = BsonExpression.Create(\"{ Name: UPPER($.Name) }\");\nif (transform.Type != BsonExpressionType.Document)\n{\n    throw new InvalidOperationException(\"UpdateMany transform must be a document expression.\");\n}\ncollection.UpdateMany(transform, BsonExpression.Create(\"_id > 0\"));","typeGuard":"static bool IsDocumentExpression(BsonExpression expr) => expr?.Type == BsonExpressionType.Document;","tryCatchPattern":"try\n{\n    collection.UpdateMany(transform, predicate);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"must return a document\"))\n{\n    logger.LogError(\"UpdateMany transform must be a {{ ... }} document expression.\");\n    throw;\n}","preventionTips":["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."],"tags":["update","expression","updatemany","argument"],"backgroundTag":null,"analyzedSha":"f906a5f850678719e39a39a006cb66dcae563cfa","analyzedAt":"2026-08-13T21:56:30.148Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}