elsa-workflows/elsa-core · error · DocumentStoreValidationException
Storage unit ' ' requires index values for fields ' '.
Error message
Storage unit '{collection.Name}' requires index values for fields '{string.Join(", ", missingFields)}'. What it means
SaveAsync requires the request to supply index values for every field defined across the collection's indexes. Missing fields would make it impossible to build the index entries MongoDB needs, so ValidateSaveRequest throws DocumentStoreValidationException listing the exact missing field names and the storage unit (collection) they belong to.
Solutions
- Add the missing field(s) named in the message to request.IndexValues before calling SaveAsync.
- Compare field names exactly (ordinal, case-sensitive) between collection.Indexes field definitions and your IndexValues keys.
- If the index definition changed, update all writers or write a migration that populates the new index value for documents.
Example fix
// before
var request = new SaveDocumentRequest { Id = id, IndexValues = new Dictionary<string, string?> { ["orderId"] = orderId } };
// after (collection indexes on orderId and customerEmail)
var request = new SaveDocumentRequest { Id = id, IndexValues = new Dictionary<string, string?> { ["orderId"] = orderId, ["customerEmail"] = customerEmail } }; Defensive patterns
Strategy: validation
Validate before calling
var requiredFields = collection.Indexes.SelectMany(i => i.Fields).Distinct(StringComparer.Ordinal).ToList();
var missing = requiredFields.Where(f => !request.IndexValues.ContainsKey(f)).ToList();
if (missing.Count > 0)
throw new InvalidOperationException($"Missing index values: {string.Join(", ", missing)}"); Try / catch
try
{
await store.SaveAsync(collection, request, ct);
}
catch (DocumentStoreValidationException ex)
{
logger.LogError(ex, "Missing index values for storage unit {Unit}", collection.Name);
throw;
} Prevention
- Derive IndexValues keys from the same source of truth as the index definitions; never hard-code field names twice.
- Remember key comparison is ordinal/case-sensitive — match field names exactly.
- When adding an indexed field, update all write paths and backfill in the same change.
When it happens
Trigger: Calling SaveAsync where collection.Indexes define field(s) that request.IndexValues does not contain (missing key, or key with different casing — the comparison is ordinal and case-sensitive).
Common situations: Adding a new indexed field to the collection schema without backfilling/supplying that field on existing write paths; renaming a field in the index definition while callers still use the old key; case mismatch like 'OrderId' vs 'orderId'.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Storage unit ' ' is not declared in the persistence schema.
- Document ID is required.
- Document ' ' in storage unit ' ' expected version ' ' but…
- Document ' ' in storage unit ' ' expected version ' ' but…
- Storage unit ' ' is not declared in the persistence schema.
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/4c7c02eb6c89eff9.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Persistence.VNext.MongoDb/MongoDbDocumentStore.cs:161
var exists = await cursor.MoveNextAsync(cancellationToken) && cursor.Current.Any();
if (!exists)
await _database.CreateCollectionAsync(collectionName, cancellationToken: cancellationToken);
}
private static void ValidateSaveRequest(DocumentCollection collection, SaveDocumentRequest request)
{
if (string.IsNullOrWhiteSpace(request.Id))
throw new DocumentStoreValidationException("Document ID is required.");
var missingFields = collection.Indexes
.SelectMany(x => x.Fields)
.Distinct(StringComparer.Ordinal)
.Where(field => !request.IndexValues.ContainsKey(field))
.Order(StringComparer.Ordinal)
.ToList();
if (missingFields.Count > 0)
throw new DocumentStoreValidationException($"Storage unit '{collection.Name}' requires index values for fields '{string.Join(", ", missingFields)}'.");
}
private static void ValidateExpectedVersion(string storageUnit, string documentId, long? expectedVersion, long? actualVersion)
{
if (expectedVersion is null)
return;
if (expectedVersion != (actualVersion ?? 0))
throw new DocumentStoreConcurrencyException(storageUnit, documentId, expectedVersion, actualVersion);
}
private static async Task<StoredDocument?> LoadDocumentAsync(IMongoCollection<BsonDocument> collection, string storageUnit, string id, CancellationToken cancellationToken)
{
var document = await collection.Find(Builders<BsonDocument>.Filter.Eq("_id", id)).FirstOrDefaultAsync(cancellationToken);
return document is null ? null : ReadDocument(document, storageUnit);
}
private static FilterDefinition<BsonDocument> CreateSaveFilter(SaveDocumentRequest request)View on GitHub (pinned to fe9217bdfa)