elsa-workflows/elsa-core · error · InvalidOperationException
Type does not expose an Add method for .
Error message
Type {collectionType} does not expose an Add method for {desiredCollectionItemType}. What it means
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.
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
Example fix
// before
public ISet<MyItem> Items { get; set; }
// after (use a concrete closed generic)
public HashSet<MyItem> Items { get; set; } Defensive patterns
Strategy: try-catch
Validate before calling
// ensure closed generic collection types
if (targetType.IsGenericType && targetType.GetGenericArguments().Length != targetType.GetGenericArguments().Length)
throw new InvalidOperationException("Use closed generic collections"); Try / catch
try { collection = ObjectConverter.ConvertTo(source, collectionType); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Add method")) { collection = default; } Prevention
- 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
When it happens
Trigger: 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).
Common situations: Rare; encountered after upgrades or when the desired collection item type derivation changes (e.g. generic type resolution against custom set interfaces).
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Type ' ' not found.
- Failed to deserialize
- Failed to convert an object of type
- Invalid value type.
- Invalid target type.
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/0d8086650387ae93.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Expressions/Helpers/ObjectConverter.cs:278
s
};
}
if (value is IEnumerable enumerable)
{
if (underlyingTargetType is { IsGenericType: true })
{
var desiredCollectionItemType = targetType.GenericTypeArguments[0];
var desiredCollectionType = typeof(ICollection<>).MakeGenericType(desiredCollectionItemType);
var desiredSetType = typeof(ISet<>).MakeGenericType(desiredCollectionItemType);
if (underlyingTargetType.IsAssignableFrom(desiredCollectionType) || desiredCollectionType.IsAssignableFrom(underlyingTargetType))
{
var collectionType = desiredSetType.IsAssignableFrom(underlyingTargetType)
? typeof(HashSet<>).MakeGenericType(desiredCollectionItemType)
: typeof(List<>).MakeGenericType(desiredCollectionItemType);
var collection = Activator.CreateInstance(collectionType)!;
var addMethod = collectionType.GetMethod("Add", [desiredCollectionItemType]) ?? throw new InvalidOperationException($"Type {collectionType} does not expose an Add method for {desiredCollectionItemType}.");
foreach (var item in enumerable)
{
var convertedItem = ConvertTo(item, desiredCollectionItemType);
addMethod.Invoke(collection, [convertedItem]);
}
return collection;
}
}
if (underlyingTargetType.IsArray)
{
var executedEnumerable = enumerable.Cast<object>().ToList();
var underlyingTargetElementType = underlyingTargetType.GetElementType()!;
var array = Array.CreateInstance(underlyingTargetElementType, executedEnumerable.Count);
var index = 0;
foreach (var item in executedEnumerable)View on GitHub (pinned to fe9217bdfa)