dotnet/wpf · error · InvalidOperationException

SR.PropertyNotReadOnly

Error message

SR.PropertyNotReadOnly

What it means

OverrideMetadata throws this InvalidOperationException when a key is passed (the three-argument overload) but the property is NOT read-only. Keys exist exclusively to authorize operations on read-only properties, so supplying a DependencyPropertyKey for a writable property is a programming error.

Solutions

  1. Use the two-argument overload: writableDp.OverrideMetadata(forType, typeMetadata)
  2. Remove the DependencyPropertyKey argument from the call
  3. Keep separate helper methods for read-only vs writable metadata overrides so keys are only threaded through read-only paths

Example fix

// before
MyWritableProperty.OverrideMetadata(typeof(MyControl), meta, SomeReadOnlyKey); // throws
// after
MyWritableProperty.OverrideMetadata(typeof(MyControl), meta); // writable DP takes no key
Defensive patterns

Strategy: validation

Validate before calling

if (!dp.ReadOnly && key != null)
    throw new InvalidOperationException("Writable DP: use the two-argument OverrideMetadata");

Prevention

When it happens

Trigger: Calling writableDp.OverrideMetadata(forType, typeMetadata, someKey) where writableDp was registered with DependencyProperty.Register (not RegisterReadOnly).

Common situations: Copy-pasting an override call from a read-only DP to a writable one and leaving the key argument in place; a helper method that always forwards a key.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/DependencyProperty.cs:538

            SetupOverrideMetadata(forType, typeMetadata, out dType, out baseMetadata);

            ArgumentNullException.ThrowIfNull(key);

            if (ReadOnly)
            {
                // If the property is read-only, the key must match this property
                //  and the key must match that in the base metadata.

                if (key.DependencyProperty != this)
                {
                    throw new ArgumentException(SR.Format(SR.ReadOnlyOverrideKeyNotAuthorized, Name));
                }

                VerifyReadOnlyKey(key);
            }
            else
            {
                throw new InvalidOperationException(SR.PropertyNotReadOnly);
            }

            // Either the property doesn't require a key, or the key match was
            //  successful.  Proceed with the metadata override.
            ProcessOverrideMetadata(forType, typeMetadata, dType, baseMetadata);
        }

        /// <summary>
        ///     After parameters have been validated for OverrideMetadata, this
        /// method is called to actually update the data structures.
        /// </summary>
        private void ProcessOverrideMetadata(
            Type forType,
            PropertyMetadata typeMetadata,
            DependencyObjectType dType,
            PropertyMetadata baseMetadata)
        {
            // Store per-Type metadata for this property. Locks only on Write.

View on GitHub (pinned to 81131a70a4)