dotnet/wpf · error · NotSupportedException

SR.NotSupported_ReadOnlyCollection

Error message

SR.NotSupported_ReadOnlyCollection

What it means

WeakReadOnlyCollection is, by contract, read-only: its IList<T> indexer's setter always throws NotSupportedException with SR.NotSupported_ReadOnlyCollection. The collection wraps weak references (this getter resolves list[index].Target), so mutating it through the read-only view is never allowed. Any write through the IList<T> interface fails unconditionally.

Solutions

  1. Don't mutate the read-only view: rebuild a new collection/list and replace the reference instead of writing in place.
  2. If mutation is needed, keep the underlying mutable collection and wrap it only for read-only consumers.
  3. Check for IReadOnlyList<T>/ReadOnlyCollection APIs instead of casting to IList<T> and writing.
  4. Guard generic IList<T>-accepting helpers with IsReadOnly before writing (IList.IsReadOnly returns true here).

Example fix

// before
var list = (IList<string>)weakReadOnly;
list[0] = "new"; // NotSupportedException
// after
if (list.IsReadOnly) throw new InvalidOperationException("collection is read-only");
var copy = new List<string>(weakReadOnly);
copy[0] = "new";
Defensive patterns

Strategy: type-guard

Validate before calling

if (((IList<T>)collection).IsReadOnly)
    throw new InvalidOperationException("Cannot write into a read-only collection; build a new one instead.");

Type guard

bool IsWritable<T>(ICollection<T> c) => c is not WeakReadOnlyCollection<T> && !c.IsReadOnly;

Try / catch

try
{
    ((IList<T>)collection)[index] = item;
}
catch (NotSupportedException)
{
    var copy = new List<T>(collection);
    copy[index] = item;
    ReplaceCollection(copy);
}

Prevention

When it happens

Trigger: Assigning through the indexer of a WeakReadOnlyCollection cast to IList<T>, e.g. ((IList<T>)weakCollection)[i] = item, or via code that accepts IList<T> and writes into it.

Common situations: Passing the read-only wrapper to helper methods that take IList<T> and mutate in place (sorting, updating, filling); assuming a read-only wrapper supports index assignment; old code refactored from a mutable List<T> to a read-only view.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/55fdc42d1ea1fc11. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Collections/ObjectModel/WeakReadOnlyCollection.cs:81

        /*
        protected IList<T> Items {
            get {
                return list;
            }
        }
        */

        bool ICollection<T>.IsReadOnly {
            get { return true; }
        }

        T IList<T>.this[int index] {
            //get { return list[index]; }
            get { return (T)list[index].Target; }
            set {
                //ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
                throw new NotSupportedException(SR.NotSupported_ReadOnlyCollection);
            }
        }

        void ICollection<T>.Add(T value) {
            //ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
            throw new NotSupportedException(SR.NotSupported_ReadOnlyCollection);
        }

        void ICollection<T>.Clear() {
            //ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
            throw new NotSupportedException(SR.NotSupported_ReadOnlyCollection);
        }

        void IList<T>.Insert(int index, T value) {
            //ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
            throw new NotSupportedException(SR.NotSupported_ReadOnlyCollection);
        }

View on GitHub (pinned to 81131a70a4)