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
- Don't mutate the read-only view: rebuild a new collection/list and replace the reference instead of writing in place.
- If mutation is needed, keep the underlying mutable collection and wrap it only for read-only consumers.
- Check for IReadOnlyList<T>/ReadOnlyCollection APIs instead of casting to IList<T> and writing.
- 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
- Treat ReadOnly*/weak read-only wrappers as immutable; never cast down to IList<T> to write
- Expose IReadOnlyList<T> instead of IList<T> in your APIs to prevent accidental writes
- Prefer copy-on-write: build a new collection and swap the reference
- Check ICollection<T>.IsReadOnly in generic helpers before mutating
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)