{"record":{"id":"7ede767be085049c","repo":"elsa-workflows/elsa-core","slug":"document-id-is-required-relationaldocumentstore","errorCode":null,"errorMessage":"Document ID is required.","messagePattern":"Document ID is required\\.","errorType":"validation","errorClass":"DocumentStoreValidationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Persistence.VNext.Relational/Documents/RelationalDocumentStore.cs","lineNumber":119,"sourceCode":"            var document = await LoadAsync(transaction, query.StorageUnit, documentId, cancellationToken);\n            if (document is not null)\n                documents.Add(document);\n        }\n\n        await transaction.CommitAsync(cancellationToken);\n        return documents;\n    }\n\n    private DocumentCollection GetCollection(string storageUnit)\n    {\n        return _plan.Collections.SingleOrDefault(x => string.Equals(x.Name, storageUnit, StringComparison.Ordinal))\n            ?? throw new DocumentStoreValidationException($\"Storage unit '{storageUnit}' is not declared in the persistence schema.\");\n    }\n\n    private static void ValidateSaveRequest(DocumentCollection collection, SaveDocumentRequest request)\n    {\n        if (string.IsNullOrWhiteSpace(request.Id))\n            throw new DocumentStoreValidationException(\"Document ID is required.\");\n\n        var missingFields = collection.Indexes\n            .SelectMany(x => x.Fields)\n            .Distinct(StringComparer.Ordinal)\n            .Where(field => !request.IndexValues.ContainsKey(field))\n            .Order(StringComparer.Ordinal)\n            .ToList();\n\n        if (missingFields.Count > 0)\n            throw new DocumentStoreValidationException($\"Storage unit '{collection.Name}' requires index values for fields '{string.Join(\", \", missingFields)}'.\");\n    }\n\n    private static void ValidateExpectedVersion(string storageUnit, string documentId, long? expectedVersion, long? actualVersion)\n    {\n        if (expectedVersion is null)\n            return;\n\n        if (expectedVersion != (actualVersion ?? 0))","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Persistence.VNext.Relational/Documents/RelationalDocumentStore.cs#L101-L137","documentation":"SaveAsync validates each save request before writing. A document with a null, empty, or whitespace-only Id cannot be identified or keyed in the store, so SaveAsync throws DocumentStoreValidationException. The Id is the primary identity used for upserts and versioning.","triggerScenarios":"Calling SaveAsync with a SaveDocumentRequest whose Id property is null, empty string, or whitespace.","commonSituations":"Building the request dynamically and forgetting to assign the Id; a domain object whose identifier field was never populated (e.g. new entity that should have gotten an ID from a generator); deserialization produced a default/empty ID.","solutions":["Populate SaveDocumentRequest.Id before calling SaveAsync.","If the entity is new, generate an identifier (Guid.NewGuid().ToString(\"N\") or your ID generator) prior to saving.","Check upstream mapping code that constructs the request to ensure the source object's ID is not lost during mapping."],"exampleFix":"// before\nawait store.SaveAsync(collection, new SaveDocumentRequest { Data = doc });\n// after\nawait store.SaveAsync(collection, new SaveDocumentRequest { Id = doc.Id ?? Guid.NewGuid().ToString(\"N\"), Data = doc });","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(request.Id)) throw new InvalidOperationException(\"Cannot save document without an Id.\");","typeGuard":null,"tryCatchPattern":"try { await store.SaveAsync(collection, request); }\ncatch (DocumentStoreValidationException ex) { logger.LogError(ex, \"Invalid save request\"); throw; }","preventionTips":["Make Id a required constructor parameter of your request-building code.","Generate IDs at entity creation time, not at save time.","Add a unit test asserting every save path sets an Id."],"tags":["persistence","validation","document-id"],"backgroundTag":"missing-required-argument","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}