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

  1. Add the missing field(s) named in the message to request.IndexValues before calling SaveAsync.
  2. Compare field names exactly (ordinal, case-sensitive) between collection.Indexes field definitions and your IndexValues keys.
  3. 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

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


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)