dotnet/wpf · error · InvalidOperationException

SR.ReadOnlyChangeNotAllowed

Error message

SR.ReadOnlyChangeNotAllowed

What it means

DependencyObject.SetupPropertyChange (used by SetValue/ClearValue via CheckReadOnly) throws InvalidOperationException(SR.ReadOnlyChangeNotAllowed, dp.Name) when the target DependencyProperty is read-only (ReadOnly=true, registered via DependencyPropertyKey). Read-only DPs (e.g. many system/modeled properties like IsMouseOver) can only be set through their internal key.

Solutions

  1. Use the DependencyPropertyKey (if you own the property or it's exposed via internal API) instead of the public DP.
  2. Check dp.ReadOnly before SetValue/ClearValue and skip read-only properties.
  3. For state simulation, use the intended mechanism (e.g. RaiseEvent for mouse, or a TestHook) rather than writing read-only DPs.

Example fix

// before
if (property.IsMouseOverProperty != null)
    element.SetValue(UIElement.IsMouseOverProperty, true);
// after
if (!UIElement.IsMouseOverProperty.ReadOnly)
    element.SetValue(UIElement.IsMouseOverProperty, true);
else
    /* simulate via input events */;
Defensive patterns

Strategy: type-guard

Validate before calling

if (dp == null || dp.ReadOnly)
    return; // skip read-only dependency properties

Type guard

bool IsWritable(DependencyProperty dp) => dp != null && !dp.ReadOnly;

Try / catch

try { obj.SetValue(dp, value); }
catch (InvalidOperationException ex) when (ex.Message.Contains(dp.Name))
{
    log.LogWarning($"{dp.Name} is read-only; use its DependencyPropertyKey or events instead.");
}

Prevention

When it happens

Trigger: Calling SetValue(SomeReadOnlyProperty, value) or ClearValue(SomeReadOnlyProperty) on properties registered read-only, e.g. attempting UIElement.IsMouseOver = true or writing to a read-only DP you registered yourself with AddOwner without the key.

Common situations: Trying to simulate mouse states in tests; writing to read-only DPs exposed by third-party controls; reflection-based property assignment enumerating all DPs including read-only ones.

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/eddd5f235b025379. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/DependencyObject.cs:590

            SetValueCommon(dp, value, metadata, coerceWithDeferredReference: false, coerceWithCurrentValue: false, OperationType.Unknown, isInternal: false);
        }

        /// <summary>
        ///     Called by SetValue or ClearValue to verify that the property
        /// can be changed.
        /// </summary>
        private PropertyMetadata SetupPropertyChange(DependencyProperty dp)
        {
            ArgumentNullException.ThrowIfNull(dp);

            if (!dp.ReadOnly)
            {
                // Get type-specific metadata for this property
                return dp.GetMetadata(DependencyObjectType);
            }
            else
            {
                throw new InvalidOperationException(SR.Format(SR.ReadOnlyChangeNotAllowed, dp.Name));
            }
        }

        /// <summary>
        ///     Called by SetValue or ClearValue to verify that the property
        /// can be changed.
        /// </summary>
        private PropertyMetadata SetupPropertyChange(DependencyPropertyKey key, out DependencyProperty dp)
        {
            ArgumentNullException.ThrowIfNull(key);

            dp = key.DependencyProperty;
            Debug.Assert(dp != null);

            dp.VerifyReadOnlyKey(key);

            // Get type-specific metadata for this property
            return dp.GetMetadata(DependencyObjectType);

View on GitHub (pinned to 81131a70a4)