{"record":{"id":"0d8086650387ae93","repo":"elsa-workflows/elsa-core","slug":"type-collectiontype-does-not-expose-an-add-method-for","errorCode":null,"errorMessage":"Type {collectionType} does not expose an Add method for {desiredCollectionItemType}.","messagePattern":"Type (.+?) does not expose an Add method for (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Expressions/Helpers/ObjectConverter.cs","lineNumber":278,"sourceCode":"                    s\n                };\n        }\n\n        if (value is IEnumerable enumerable)\n        {\n            if (underlyingTargetType is { IsGenericType: true })\n            {\n                var desiredCollectionItemType = targetType.GenericTypeArguments[0];\n                var desiredCollectionType = typeof(ICollection<>).MakeGenericType(desiredCollectionItemType);\n                var desiredSetType = typeof(ISet<>).MakeGenericType(desiredCollectionItemType);\n\n                if (underlyingTargetType.IsAssignableFrom(desiredCollectionType) || desiredCollectionType.IsAssignableFrom(underlyingTargetType))\n                {\n                    var collectionType = desiredSetType.IsAssignableFrom(underlyingTargetType)\n                        ? typeof(HashSet<>).MakeGenericType(desiredCollectionItemType)\n                        : typeof(List<>).MakeGenericType(desiredCollectionItemType);\n                    var collection = Activator.CreateInstance(collectionType)!;\n                    var addMethod = collectionType.GetMethod(\"Add\", [desiredCollectionItemType]) ?? throw new InvalidOperationException($\"Type {collectionType} does not expose an Add method for {desiredCollectionItemType}.\");\n\n                    foreach (var item in enumerable)\n                    {\n                        var convertedItem = ConvertTo(item, desiredCollectionItemType);\n                        addMethod.Invoke(collection, [convertedItem]);\n                    }\n\n                    return collection;\n                }\n            }\n\n            if (underlyingTargetType.IsArray)\n            {\n                var executedEnumerable = enumerable.Cast<object>().ToList();\n                var underlyingTargetElementType = underlyingTargetType.GetElementType()!;\n                var array = Array.CreateInstance(underlyingTargetElementType, executedEnumerable.Count);\n                var index = 0;\n                foreach (var item in executedEnumerable)","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Expressions/Helpers/ObjectConverter.cs#L260-L296","documentation":"When ConvertTo converts an enumerable to a set- or collection-typed target, it instantiates a HashSet<> or List<> of the desired item type and reflects for an Add method with the exact item parameter type. If the constructed collection type lacks such an Add method it throws InvalidOperationException — effectively an internal invariant violation.","triggerScenarios":"Converting an enumerable into ICollection<T>/ISet<T>-like targets where Activator-created HashSet<T>/List<T> does not expose Add(T) — practically a bug or unusual generic configuration (e.g. desiredCollectionItemType resolved incorrectly).","commonSituations":"Rare; encountered after upgrades or when the desired collection item type derivation changes (e.g. generic type resolution against custom set interfaces).","solutions":["Inspect how desiredCollectionItemType/desiredSetType are derived and ensure the target type is a closed generic collection (e.g. ISet<int>, not ISet<> or a custom set type)","Convert to a concrete collection type (List<T>/HashSet<T>) instead of a custom set interface in the target property","Catch InvalidOperationException in ConvertTo callers (or file a bug with the exact target type) since this indicates an unsupported conversion path"],"exampleFix":"// before\npublic ISet<MyItem> Items { get; set; }\n// after (use a concrete closed generic)\npublic HashSet<MyItem> Items { get; set; }","handlingStrategy":"try-catch","validationCode":"// ensure closed generic collection types\nif (targetType.IsGenericType && targetType.GetGenericArguments().Length != targetType.GetGenericArguments().Length)\n    throw new InvalidOperationException(\"Use closed generic collections\");","typeGuard":null,"tryCatchPattern":"try { collection = ObjectConverter.ConvertTo(source, collectionType); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Add method\")) { collection = default; }","preventionTips":["Use concrete closed generic collections (List<T>, HashSet<T>) as targets","Avoid custom set interfaces as conversion targets","Report persistent occurrences as an Elsa bug with the exact types"],"tags":["csharp","reflection","type-conversion","collections"],"backgroundTag":"internal-invariant-violation","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"}