dotnet/wpf · error · InvalidOperationException
SR.VisualCollection_ReadOnly
Error message
SR.VisualCollection_ReadOnly
What it means
Thrown by VisualCollection.VerifyNotReadOnly when a write operation is attempted on a read-only VisualCollection. WPF marks collections read-only in specific internal contexts (e.g. during enumeration or for system-owned collections), and any Add/Insert/Remove/Clear on them is invalid.
Solutions
- Check VisualCollection.IsReadOnly (or IsReadOnlyInternal) before mutating and skip/queue the change.
- Perform child modifications outside the read-only window (e.g. after Measure/Arrange completes, via Dispatcher).
- Add/remove children via the owning Visual's API on a UI thread at a safe point rather than inside iteration.
Example fix
// before
visuals.Add(newChild); // throws when collection is read-only
// after
if (!visuals.IsReadOnly)
{
visuals.Add(newChild);
} Defensive patterns
Strategy: validation
Validate before calling
if (visualCollection.IsReadOnly)
{
// queue the mutation for later
}
else
{
visualCollection.Add(child);
} Type guard
static bool CanMutate(VisualCollection c) => !c.IsReadOnly;
Try / catch
try { collection.Add(child); }
catch (InvalidOperationException) { /* collection locked read-only; defer */ } Prevention
- Check IsReadOnly before every mutation of a VisualCollection you don't own.
- Don't mutate collections returned from read-only WPF API paths.
- Perform child changes on the UI thread outside layout/render callbacks.
When it happens
Trigger: Calling Add, Insert, Remove, RemoveAt, or Clear on a VisualCollection whose IsReadOnlyInternal is true — typically a collection obtained from a context where WPF has locked it (e.g. during read-only API paths like CopyTo's VerifyAPIReadOnly usage or system-driven visual management).
Common situations: Custom panels/framework code modifying children while WPF holds the collection read-only; writing to a visual's children inside layout or rendering callbacks that obtained the collection in a locked state.
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
- throw new NotSupportedException();
- 0x80040209
- Cannot pass multidimensional array to the CopyTo method on…
- Cannot remove signature from read-only file.
- Cannot sign read-only file.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/35850ca48cf8bacb.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/VisualCollection.cs:98
internal void VerifyAPIReadWrite()
{
Debug.Assert(_owner != null);
_owner.VerifyAPIReadWrite();
VerifyNotReadOnly();
}
internal void VerifyAPIReadWrite(Visual other)
{
Debug.Assert(_owner != null);
_owner.VerifyAPIReadWrite(other);
VerifyNotReadOnly();
}
internal void VerifyNotReadOnly()
{
if (IsReadOnlyInternal)
{
throw new InvalidOperationException(SR.VisualCollection_ReadOnly);
}
}
/// <summary>
/// Gets the number of elements in the collection.
/// </summary>
public int Count
{
get
{
VerifyAPIReadOnly();
return InternalCount;
}
}
/// <summary>
/// True if the collection allows modifications, otherwise false.View on GitHub (pinned to 81131a70a4)