dotnet/maui · warning · NotSupportedException

void ICollection<Element>.Add(Element item) => throw new Not

Error message

void ICollection<Element>.Add(Element item) => throw new NotSupportedException();

What it means

Thrown by TemporaryWrapper.Add(Element). TemporaryWrapper is a read-only IList<Element> adapter (IsReadOnly = true) used internally by the obsolete Element.LogicalChildren property to expose children as a ReadOnlyCollection. All mutating operations throw NotSupportedException.

Source

Thrown at src/Controls/src/Core/Element/Element.cs:1201

			return false;
		}

		class TemporaryWrapper : IList<Element>
		{
			IReadOnlyList<Element> _inner;

			public TemporaryWrapper(IReadOnlyList<Element> inner)
			{
				_inner = inner;
			}

			Element IList<Element>.this[int index] { get => _inner[index]; set => throw new NotSupportedException(); }

			int ICollection<Element>.Count => _inner.Count;

			bool ICollection<Element>.IsReadOnly => true;

			void ICollection<Element>.Add(Element item) => throw new NotSupportedException();

			void ICollection<Element>.Clear() => throw new NotSupportedException();

			bool ICollection<Element>.Contains(Element item) => _inner.IndexOf(item) != -1;

			void ICollection<Element>.CopyTo(Element[] array, int arrayIndex) => throw new NotSupportedException();

			IEnumerator<Element> IEnumerable<Element>.GetEnumerator() => _inner.GetEnumerator();

			System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => _inner.GetEnumerator();

			int IList<Element>.IndexOf(Element item) => _inner.IndexOf(item);

			void IList<Element>.Insert(int index, Element item) => throw new NotSupportedException();

			bool ICollection<Element>.Remove(Element item) => throw new NotSupportedException();

			void IList<Element>.RemoveAt(int index) => throw new NotSupportedException();

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Use InsertLogicalChild to add logical children instead of mutating the collection.
  2. Treat LogicalChildren as read-only; never write through it or its backing wrapper.
  3. Avoid reflecting into Element internals.

Example fix

// before (reflection on internal wrapper)
wrapper.Add(child); // NotSupportedException
// after
element.InsertLogicalChild(element.LogicalChildren.Count, child);
Defensive patterns

Strategy: validation

Validate before calling

if (element.LogicalChildren.IsReadOnly)
    return; // do not call Add on the backing wrapper

Try / catch

// Adapter reached only via reflection; callers should use InsertLogicalChild instead.

Prevention

When it happens

Trigger: Obtaining the internal TemporaryWrapper (e.g., through reflection or inside Hot Reload code) and calling Add on it. The public LogicalChildren returns a ReadOnlyCollection<Element> that already guards against this; reaching TemporaryWrapper.Add requires bypassing that guard.

Common situations: Reflection/serialization frameworks enumerating and mutating internal collections; Hot Reload or designer tooling that writes to the backing list; incorrect assumption that LogicalChildren is mutable.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/cfcbf9a7bea50bca. Report an issue: GitHub.