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

Every field covered by a declared index on a storage unit must be supplied as an index value in the save request, since these values populate physical index columns. SaveAsync collects all missing indexed fields and reports them in one DocumentStoreValidationException.

Solutions

  1. Add values for every missing field listed in the message to request.IndexValues before saving.
  2. Compare index field names in the schema with the keys you populate — names must match exactly.
  3. If the index is new, backfill existing documents and update the save path to emit the new index values.
  4. Make index-value population derive from the same constant/property used to declare the index so they cannot diverge.

Example fix

// before
var request = new SaveDocumentRequest { Id = doc.Id, Data = doc, IndexValues = { ["CorrelationId"] = doc.CorrelationId } };
// after
var request = new SaveDocumentRequest { Id = doc.Id, Data = doc, IndexValues = { ["CorrelationId"] = doc.CorrelationId, ["Status"] = doc.Status } }; // Status is an indexed field
Defensive patterns

Strategy: validation

Validate before calling

var missing = collection.Indexes.SelectMany(i => i.Fields).Distinct()
    .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); }
catch (DocumentStoreValidationException ex) { logger.LogError(ex, "Index values incomplete for {Unit}", collection.Name); throw; }

Prevention

When it happens

Trigger: Calling SaveAsync where request.IndexValues lacks a key for at least one field referenced by collection.Indexes.

Common situations: Adding a new index to the schema without backfilling/producing the corresponding index value in save code; field-name casing mismatch (keys are compared with ContainsKey, case-sensitive); saving an older document shape against an updated schema.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/6c53f5c36bc2cec4. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.Persistence.VNext.Relational/Documents/RelationalDocumentStore.cs:129

    {
        return _plan.Collections.SingleOrDefault(x => string.Equals(x.Name, storageUnit, StringComparison.Ordinal))
            ?? throw new DocumentStoreValidationException($"Storage unit '{storageUnit}' is not declared in the persistence schema.");
    }

    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 async Task OpenAsync(CancellationToken cancellationToken)
    {
        if (_connection.State != ConnectionState.Open)
            await _connection.OpenAsync(cancellationToken);
    }

    private async Task<StoredDocument?> LoadAsync(DbTransaction? transaction, string storageUnit, string id, CancellationToken cancellationToken)

View on GitHub (pinned to fe9217bdfa)