{"record":{"id":"c56b3c6418093e39","repo":"litedb-org/LiteDB","slug":"0-c56b3c","errorCode":"0","errorMessage":"Multikey index expression do not support unique option","messagePattern":"Multikey index expression do not support unique option","errorType":"exception","errorClass":"LiteException","httpStatus":null,"severity":"error","filePath":"LiteDB/Engine/Engine/Index.cs","lineNumber":25,"sourceCode":"\nnamespace LiteDB.Engine\n{\n    public partial class LiteEngine\n    {\n        /// <summary>\n        /// Create a new index (or do nothing if already exists) to a collection/field\n        /// </summary>\n        public bool EnsureIndex(string collection, string name, BsonExpression expression, bool unique)\n        {\n            if (collection.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(collection));\n            if (name.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(name));\n            if (expression == null) throw new ArgumentNullException(nameof(expression));\n            if (expression.IsIndexable == false) throw new ArgumentException(\"Index expressions must contains at least one document field. Used methods must be immutable. Parameters are not supported.\", nameof(expression));\n\n            if (name.Length > INDEX_NAME_MAX_LENGTH) throw LiteException.InvalidIndexName(name, collection, \"MaxLength = \" + INDEX_NAME_MAX_LENGTH);\n            if (!name.IsWord()) throw LiteException.InvalidIndexName(name, collection, \"Use only [a-Z$_]\");\n            if (name.StartsWith(\"$\")) throw LiteException.InvalidIndexName(name, collection, \"Index name can't start with `$`\");\n            if (expression.IsScalar == false && unique) throw new LiteException(0, \"Multikey index expression do not support unique option\");\n\n            if (expression.Source == \"$._id\") return false; // always exists\n\n            return this.AutoTransaction(transaction =>\n            {\n                var snapshot = transaction.CreateSnapshot(LockMode.Write, collection, true);\n                var collectionPage = snapshot.CollectionPage;\n                var indexer = new IndexService(snapshot, _header.Pragmas.Collation, _disk.MAX_ITEMS_COUNT);\n                var data = new DataService(snapshot, _disk.MAX_ITEMS_COUNT);\n\n                // check if index already exists\n                var current = collectionPage.GetCollectionIndex(name);\n\n                // if already exists, just exit\n                if (current != null)\n                {\n                    // but if expression are different, throw error\n                    if (current.Expression != expression.Source) throw LiteException.IndexAlreadyExist(name);","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/litedb-org/LiteDB/blob/f906a5f850678719e39a39a006cb66dcae563cfa/LiteDB/Engine/Engine/Index.cs#L7-L43","documentation":"Thrown by EnsureIndex when the index expression is non-scalar (multikey, i.e., can produce multiple index entries per document, like an array path) AND the unique flag is set to true. Unique indexes require exactly one key per document, so multikey expressions are incompatible with uniqueness. This is a LiteException (code 0) thrown at validation time before any index is created.","triggerScenarios":"Calling `EnsureIndex(collection, name, \"$.tags\", unique: true)` where $.tags is an array field. Any non-scalar expression (containing [*], MAP, etc.) passed with unique=true.","commonSituations":"Attempting to enforce uniqueness on an array field. Copying index definitions from a schema where an array field was mistakenly marked unique. Programmatically generating indexes without checking expression scalar-ness against the unique flag.","solutions":["Set unique=false for multikey/array expressions.","Change the expression to a scalar field if uniqueness is truly required, e.g., index a single-value field instead of an array.","Check `expression.IsScalar` before passing unique=true to EnsureIndex."],"exampleFix":"// before\ncol.EnsureIndex(\"idx_tags\", \"$.tags\", unique: true);\n// after\ncol.EnsureIndex(\"idx_tags\", \"$.tags\", unique: false);","handlingStrategy":"validation","validationCode":"if (unique && !expression.IsScalar)\n    throw new InvalidOperationException(\"Cannot create a unique index on a multikey expression.\");\ncol.EnsureIndex(name, expression, unique);","typeGuard":"static bool CanBeUniqueIndex(BsonExpression expr, bool unique) => !unique || expr.IsScalar;","tryCatchPattern":"try { col.EnsureIndex(name, expr, unique: true); }\ncatch (LiteException ex) when (ex.Message.Contains(\"do not support unique option\"))\n{ /* set unique=false or use a scalar expression */ }","preventionTips":["Never set unique=true on array/multikey index expressions.","Check expression.IsScalar before passing unique=true.","Review index definitions for array fields during schema review."],"tags":["engine","index","unique","multikey","validation","lite-exception"],"backgroundTag":null,"analyzedSha":"f906a5f850678719e39a39a006cb66dcae563cfa","analyzedAt":"2026-08-13T21:56:30.148Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}