dotnet/wpf · error · InvalidOperationException
SR.ClearOnReadOnlyObjectNotAllowed
Error message
SR.ClearOnReadOnlyObjectNotAllowed
What it means
Thrown by DependencyObject.ClearValueCommon when ClearValue (or the SetValue path that clears) is invoked on a sealed DependencyObject (IsSealed == true), such as a frozen Freezable or a sealed style resource. Sealed objects are immutable by design, so clearing a property is prohibited.
Solutions
- Check obj.IsSealed before calling ClearValue and skip or clone
- Call obj.Clone() (or GetAsFrozen inverse: CloneCurrentValue) to obtain a mutable copy, then ClearValue on the clone
- If it is a Freezable, work with an unfrozen copy and re-freeze after modification
- Do not attempt to unseal the original; sealed state cannot be reversed
Example fix
// before if (brush.IsFrozen) brush.ClearValue(Brush.OpacityProperty); // throws // after var mutable = brush.Clone(); mutable.ClearValue(Brush.OpacityProperty);
Defensive patterns
Strategy: validation
Validate before calling
if (depObj.IsSealed) {
depObj = ((Freezable)depObj).Clone(); // or skip
}
depObj.ClearValue(dp); Type guard
static bool CanClear(DependencyObject d) => !d.IsSealed;
Try / catch
try { depObj.ClearValue(dp); }
catch (InvalidOperationException ex) when (ex.Message.Contains("sealed") || depObj.IsSealed) { depObj = ((Freezable)depObj)?.Clone() as DependencyObject; depObj?.ClearValue(dp); } Prevention
- Check IsSealed/IsFrozen before mutating any DependencyObject/Freezable
- Clone frozen Freezables before modification
- Never mutate shared resources retrieved from dictionaries in place
When it happens
Trigger: Calling ClearValue(dp) on an object whose IsSealed property is true — e.g. a frozen Brush, a style-applied value on a sealed instance, or a shared resource retrieved from application resources.
Common situations: Trying to modify a frozen Freezable (Brush, Pen, Geometry) fetched from a resource dictionary, mutating a shared system resource, templated or sealed styles.
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
- Animation_CalculatedValueIsInvalidForProperty
- Animation_DependencyPropertyIsNotAnimatable
- CannotChangeAfterSealed
- CannotChangeAfterSealed
- InvalidOperationException()
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/f44216fd2abc182d.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/DependencyObject.cs:960
DependencyProperty dp;
// Cache the metadata object this method needed to get anyway.
PropertyMetadata metadata = SetupPropertyChange(key, out dp);
EntryIndex entryIndex = LookupEntry(dp.GlobalIndex);
ClearValueCommon(entryIndex, dp, metadata);
}
/// <summary>
/// The common code shared by all variants of ClearValue
/// </summary>
private void ClearValueCommon(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata)
{
if (IsSealed)
{
throw new InvalidOperationException(SR.Format(SR.ClearOnReadOnlyObjectNotAllowed, this));
}
// Get old value
EffectiveValueEntry oldEntry = GetValueEntry(
entryIndex,
dp,
metadata,
RequestFlags.RawEntry);
// Get current local value
// (No need to go through read local callback, just checking
// for presence of Expression)
object current = oldEntry.LocalValue;
// Get current expression
Expression currentExpr = (oldEntry.IsExpression) ? (current as Expression) : null;
// Inform value expression of detachment, if applicableView on GitHub (pinned to 81131a70a4)