litedb-org/LiteDB · error · LiteException
0
0
Error message
Multikey index expression do not support unique option
What it means
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.
Source
Thrown at LiteDB/Engine/Engine/Index.cs:25
namespace LiteDB.Engine
{
public partial class LiteEngine
{
/// <summary>
/// Create a new index (or do nothing if already exists) to a collection/field
/// </summary>
public bool EnsureIndex(string collection, string name, BsonExpression expression, bool unique)
{
if (collection.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(collection));
if (name.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(name));
if (expression == null) throw new ArgumentNullException(nameof(expression));
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));
if (name.Length > INDEX_NAME_MAX_LENGTH) throw LiteException.InvalidIndexName(name, collection, "MaxLength = " + INDEX_NAME_MAX_LENGTH);
if (!name.IsWord()) throw LiteException.InvalidIndexName(name, collection, "Use only [a-Z$_]");
if (name.StartsWith("$")) throw LiteException.InvalidIndexName(name, collection, "Index name can't start with `$`");
if (expression.IsScalar == false && unique) throw new LiteException(0, "Multikey index expression do not support unique option");
if (expression.Source == "$._id") return false; // always exists
return this.AutoTransaction(transaction =>
{
var snapshot = transaction.CreateSnapshot(LockMode.Write, collection, true);
var collectionPage = snapshot.CollectionPage;
var indexer = new IndexService(snapshot, _header.Pragmas.Collation, _disk.MAX_ITEMS_COUNT);
var data = new DataService(snapshot, _disk.MAX_ITEMS_COUNT);
// check if index already exists
var current = collectionPage.GetCollectionIndex(name);
// if already exists, just exit
if (current != null)
{
// but if expression are different, throw error
if (current.Expression != expression.Source) throw LiteException.IndexAlreadyExist(name);View on GitHub (pinned to f906a5f850)
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.
Example fix
// before
col.EnsureIndex("idx_tags", "$.tags", unique: true);
// after
col.EnsureIndex("idx_tags", "$.tags", unique: false); Defensive patterns
Strategy: validation
Validate before calling
if (unique && !expression.IsScalar)
throw new InvalidOperationException("Cannot create a unique index on a multikey expression.");
col.EnsureIndex(name, expression, unique); Type guard
static bool CanBeUniqueIndex(BsonExpression expr, bool unique) => !unique || expr.IsScalar;
Try / catch
try { col.EnsureIndex(name, expr, unique: true); }
catch (LiteException ex) when (ex.Message.Contains("do not support unique option"))
{ /* set unique=false or use a scalar expression */ } Prevention
- 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.
When it happens
Trigger: Calling `EnsureIndex(collection, name, "$.tags", unique: true)` where $.tags is an array field. Any non-scalar expression (containing [*], MAP, etc.) passed with unique=true.
Common situations: 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.
Related errors
AI-assisted analysis of litedb-org/LiteDB@f906a5f850 (2026-08-13).
Data as JSON: /api/errors/c56b3c6418093e39.
Report an issue: GitHub.