dotnet/wpf · error · ArgumentException

SR.Format(SR.TypeMustBeDependencyObjectDerived…

Error message

SR.Format(SR.TypeMustBeDependencyObjectDerived, forType.Name)

What it means

OverrideMetadata requires forType to be a DependencyObject-derived class, since only DependencyObjects participate in the WPF property system. Passing a plain CLR type throws with the type's name in the message.

Solutions

  1. Make the type derive from DependencyObject (directly or transitively) before overriding metadata.
  2. Remove the OverrideMetadata call if the type intentionally is not a DependencyObject.
  3. Move custom state to an attached-property owner that is a DependencyObject.

Example fix

// before
class MyModel { }
MyProp.OverrideMetadata(typeof(MyModel), new PropertyMetadata(1));
// after
class MyModel : DependencyObject { }
MyProp.OverrideMetadata(typeof(MyModel), new PropertyMetadata(1));
Defensive patterns

Strategy: type-guard

Validate before calling

if (!typeof(DependencyObject).IsAssignableFrom(forType)) throw new ArgumentException($"{forType.Name} must derive from DependencyObject");

Type guard

static bool CanOverrideMetadata(Type forType) => typeof(DependencyObject).IsAssignableFrom(forType);

Prevention

When it happens

Trigger: Calling dp.OverrideMetadata(typeof(SomePlainClass), new PropertyMetadata(...)) where SomePlainClass does not derive from DependencyObject.

Common situations: Attempting to override metadata for POCOs, structs, or non-visual model classes; refactoring a class to no longer inherit from DependencyObject while keeping its metadata overrides.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

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

        /// what we are overriding.
        /// </summary>
        private void SetupOverrideMetadata(
                Type forType,
                PropertyMetadata typeMetadata,
            out DependencyObjectType dType,
            out PropertyMetadata baseMetadata )
        {
            ArgumentNullException.ThrowIfNull(forType);
            ArgumentNullException.ThrowIfNull(typeMetadata);

            if (typeMetadata.Sealed)
            {
                throw new ArgumentException(SR.TypeMetadataAlreadyInUse);
            }

            if (!typeof(DependencyObject).IsAssignableFrom(forType))
            {
                throw new ArgumentException(SR.Format(SR.TypeMustBeDependencyObjectDerived, forType.Name));
            }

            // Ensure default value is a correct value (if it was supplied,
            // otherwise, the default value will be taken from the base metadata
            // which was already validated)
            if (typeMetadata.IsDefaultValueModified)
            {
                // Will throw ArgumentException if fails.
                ValidateMetadataDefaultValue( typeMetadata, PropertyType, Name, ValidateValueCallback );
            }

            // Force all base classes to register their metadata
            dType = DependencyObjectType.FromSystemType(forType);

            // Get metadata for the base type
            baseMetadata = GetMetadata(dType.BaseType);

            // Make sure overriding metadata is the same type or derived type of

View on GitHub (pinned to 81131a70a4)