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
- Use InsertLogicalChild to add logical children instead of mutating the collection.
- Treat LogicalChildren as read-only; never write through it or its backing wrapper.
- 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
- Add children via InsertLogicalChild, not by mutating LogicalChildren.
- Treat the returned collection as read-only.
- Do not reflect into Element internals.
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
- Element IList<Element>.this[int index] { get => _inner[index
- void ICollection<Element>.Clear() => throw new NotSupportedE
- void ICollection<Element>.CopyTo(Element[] array, int arrayI
- void IList<Element>.Insert(int index, Element item) => throw
- bool ICollection<Element>.Remove(Element item) => throw new
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/cfcbf9a7bea50bca.
Report an issue: GitHub.