{"record":{"id":"8981478f4692095d","repo":"elsa-workflows/elsa-core","slug":"runtime-entity-definition-definition-name-declares-field","errorCode":null,"errorMessage":"Runtime entity definition '{definition.Name}' declares field '{duplicateField.Key}' more than once.","messagePattern":"Runtime entity definition '(.+?)' declares field '(.+?)' more than once\\.","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Persistence.VNext.Runtime/Services/RuntimeEntityDefinitionValidator.cs","lineNumber":18,"sourceCode":"using Elsa.Persistence.VNext.Runtime.Models;\nusing Microsoft.Extensions.Options;\n\nnamespace Elsa.Persistence.VNext.Runtime.Services;\n\npublic class RuntimeEntityDefinitionValidator(IOptions<RuntimeEntityOptions> options)\n{\n    public void Validate(RuntimeEntityDefinition definition)\n    {\n        if (string.IsNullOrWhiteSpace(definition.Name))\n            throw new InvalidOperationException(\"Runtime entity definition name is required.\");\n\n        if (definition.Fields.Count == 0)\n            throw new InvalidOperationException($\"Runtime entity definition '{definition.Name}' must declare at least one field.\");\n\n        var duplicateField = definition.Fields.GroupBy(x => x.Name, StringComparer.OrdinalIgnoreCase).FirstOrDefault(x => x.Count() > 1);\n        if (duplicateField is not null)\n            throw new InvalidOperationException($\"Runtime entity definition '{definition.Name}' declares field '{duplicateField.Key}' more than once.\");\n\n        var maxIndexedFields = Math.Min(options.Value.MaxIndexedFields, RuntimeEntityPersistenceSchemaProvider.IndexedFieldSlotCount);\n        if (definition.Indexes.Count > maxIndexedFields)\n            throw new InvalidOperationException($\"Runtime entity definition '{definition.Name}' declares {definition.Indexes.Count} indexes, but only {maxIndexedFields} runtime index slots are available.\");\n\n        var fields = definition.Fields.Select(x => x.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);\n        foreach (var index in definition.Indexes)\n        {\n            if (!fields.Contains(index.FieldName))\n                throw new InvalidOperationException($\"Runtime entity definition '{definition.Name}' index '{index.Name}' references unknown field '{index.FieldName}'.\");\n        }\n    }\n\n    public void ValidateInstance(RuntimeEntityDefinition definition, RuntimeEntityInstance instance)\n    {\n        var dataKeys = instance.Data.Keys.ToHashSet(StringComparer.OrdinalIgnoreCase);\n        var missingField = definition.Fields.FirstOrDefault(x => x.IsRequired && !dataKeys.Contains(x.Name));\n        if (missingField is not null)","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Persistence.VNext.Runtime/Services/RuntimeEntityDefinitionValidator.cs#L1-L36","documentation":"Field names within a runtime entity definition must be unique, compared case-insensitively (OrdinalIgnoreCase). Validate groups fields by name and throws when any name appears more than once, since duplicate names make storage and index mapping ambiguous.","triggerScenarios":"Calling Validate where two or more Fields entries share the same name ignoring case — e.g. 'Status' and 'status'.","commonSituations":"Merging field lists from multiple configuration sources; appending default fields without checking whether the user already declared them; case differences from copy-paste or JSON config with case-insensitive consumers.","solutions":["Remove or rename the duplicated field so names are unique ignoring case.","Deduplicate the field list before validation, e.g. GroupBy(x => x.Name, StringComparer.OrdinalIgnoreCase) and keep one.","If a default field set is merged with user fields, skip defaults whose names already exist."],"exampleFix":"// before\ndef.Fields.Add(new RuntimeEntityField { Name = \"Status\" });\ndef.Fields.Add(new RuntimeEntityField { Name = \"status\" }); // duplicate ignoring case\n// after\ndef.Fields.Add(new RuntimeEntityField { Name = \"Status\" });","handlingStrategy":"validation","validationCode":"var dupes = definition.Fields.GroupBy(f => f.Name, StringComparer.OrdinalIgnoreCase).Where(g => g.Count() > 1).Select(g => g.Key).ToList();\nif (dupes.Count > 0) throw new InvalidOperationException($\"Duplicate fields: {string.Join(\", \", dupes)}\");","typeGuard":null,"tryCatchPattern":"try { validator.Validate(definition); }\ncatch (InvalidOperationException ex) { logger.LogError(ex, \"Duplicate fields in {Name}\", definition.Name); throw; }","preventionTips":["Deduplicate fields at build/merge time with GroupBy(OrdinalIgnoreCase).","When merging defaults with user fields, skip already-present names.","Normalize field-name casing in configuration binding."],"tags":["validation","runtime-entities","duplicates"],"backgroundTag":"schema-validation-failed","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}