tui-cs/Terminal.Gui · error · NotSupportedException

Cloning of collection type {type.Name} is not supported unle

Error message

Cloning of collection type {type.Name} is not supported unless it implements IList.

What it means

Thrown by DeepCloner.CloneCollection when the source collection implements IEnumerable but NOT IList, and is not an immutable collection (else error 38 fires). DeepCloner's collection-cloning strategy relies on IList.Add to populate the clone, so read-only or set/dictionary-style collections that lack IList are rejected.

Source

Thrown at Terminal.Gui/Configuration/DeepCloner.cs:225

    [UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "Collection cloning only instantiates the runtime collection type after filtering to supported IList implementations.")]
    private static object CloneCollection (object source, ConcurrentDictionary<object, object> visited)
    {
        Type type = source.GetType ();

        // Check for immutable collections and throw if found
        if (type.IsGenericType)
        {
            Type genericTypeDef = type.GetGenericTypeDefinition ();

            if (genericTypeDef.FullName != null && genericTypeDef.FullName.StartsWith ("System.Collections.Immutable"))
            {
                throw new NotSupportedException ($"Cloning of immutable collections like {type.Name} is not supported.");
            }
        }

        if (source is not IList)
        {
            throw new NotSupportedException ($"Cloning of collection type {type.Name} is not supported unless it implements IList.");
        }

        if (Activator.CreateInstance (type) is not IList tempList)
        {
            throw new NotSupportedException ($"Cloning of collection type {type.Name} is not supported without a parameterless constructor.");
        }

        // Add to visited before cloning contents to prevent circular reference issues
        visited.TryAdd (source, tempList);

        foreach (object? item in (IEnumerable)source)
        {
            object? clonedItem = DeepCloneInternal (item, visited);
            tempList.Add (clonedItem);
        }

        return tempList;
    }

View on GitHub (pinned to 2e47b11478)

Solutions

  1. Use a collection type that implements IList (List<T>, or for dictionaries go through CloneDictionary which handles Dictionary<,>/ConcurrentDictionary<,>).
  2. If a set is semantically required, store it as a List<T> config property and expose set semantics via a wrapper.
  3. Avoid custom collection types as config property values; DeepCloner supports a closed set of shapes.

Example fix

// before
[ConfigurationProperty] public static HashSet<string>? Tags { get; set; }
// after
[ConfigurationProperty] public static List<string>? Tags { get; set; }
Defensive patterns

Strategy: validation

Validate before calling

Type t = source.GetType ();
if (source is not IList && t.GetGenericTypeDefinition ().FullName?.StartsWith ("System.Collections.Immutable") != true)
    throw new NotSupportedException ($"{t.Name} does not implement IList; DeepCloner cannot clone it.");

Type guard

static bool IsClonableCollection (object o)
{
    Type t = o.GetType ();
    if (o is IList) return true;
    if (o is IDictionary) return true;
    return false;
}

Try / catch

try { ConfigurationManager.Apply (); }
catch (NotSupportedException ex) when (ex.Message.Contains ("not supported unless it implements IList"))
{ /* change HashSet/Set to List<T> */ }

Prevention

When it happens

Trigger: A [ConfigurationProperty] value is a collection type that does not implement IList — e.g. HashSet<T>, SortedSet<T>, a custom IEnumerable, or an IReadOnlyCollection.

Common situations: Using a HashSet/Set as a config value; a readonly collection wrapper; a custom collection that implements only IEnumerable.

Related errors


AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13). Data as JSON: /api/errors/b3240a5d84b9e25b. Report an issue: GitHub.