dotnet/wpf · error · ArgumentException

SR.Format(SR.DefaultValuePropertyTypeMismatch, propertyName)

Error message

SR.Format(SR.DefaultValuePropertyTypeMismatch, propertyName)

What it means

ValidateDefaultValueCommon checks that the default value supplied in PropertyMetadata is assignment-compatible with the property's type via IsValidType. If the default's runtime type does not match (or is not a derived type of) propertyType, registration fails. This protects the property system from handing out invalid defaults.

Solutions

  1. Make the default value exactly the property's type (or a derived type).
  2. For numeric properties, match the literal type (use 0.0 for double, 0 for int).
  3. After changing a property's type, update its PropertyMetadata default accordingly.

Example fix

// before
public static readonly DependencyProperty SizeProperty =
    DependencyProperty.Register("Size", typeof(double), typeof(MyControl),
        new PropertyMetadata(0));
// after
public static readonly DependencyProperty SizeProperty =
    DependencyProperty.Register("Size", typeof(double), typeof(MyControl),
        new PropertyMetadata(0.0));
Defensive patterns

Strategy: type-guard

Validate before calling

if (defaultValue != null && !propertyType.IsInstanceOfType(defaultValue)) throw new ArgumentException("Default value type mismatch");

Type guard

static bool IsValidDefault(object defaultValue, Type propertyType) => defaultValue == null || propertyType.IsInstanceOfType(defaultValue);

Prevention

When it happens

Trigger: new PropertyMetadata("hello") on a property registered as typeof(int); a base-type default (e.g. object) for a specific typed property; a null-typed mismatch after refactoring the property type without updating metadata.

Common situations: Changing propertyType during a refactor while leaving the old default in PropertyMetadata; copy-pasted metadata across differently-typed properties; boxed value types of the wrong kind (double 0.0 vs int).

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

        // Validate the given default value, used by PropertyMetadata.GetDefaultValue()
        // when the DefaultValue factory is used.
        // These default values are allowed to have thread-affinity.
        internal void ValidateFactoryDefaultValue(object defaultValue)
        {
            ValidateDefaultValueCommon(defaultValue, PropertyType, Name, ValidateValueCallback, false);
        }

        private static void ValidateDefaultValueCommon(
            object defaultValue,
            Type propertyType,
            string propertyName,
            ValidateValueCallback validateValueCallback,
            bool checkThreadAffinity)
        {
            // Ensure default value is the correct type
            if (!IsValidType(defaultValue, propertyType))
            {
                throw new ArgumentException(SR.Format(SR.DefaultValuePropertyTypeMismatch, propertyName));
            }

            // An Expression used as default value won't behave as expected since
            //  it doesn't get evaluated.  We explicitly fail it here.
            if (defaultValue is Expression )
            {
                throw new ArgumentException(SR.DefaultValueMayNotBeExpression);
            }

            if (checkThreadAffinity)
            {
                // If the default value is a DispatcherObject with thread affinity
                // we cannot accept it as a default value. If it implements ISealable
                // we attempt to seal it; if not we throw  an exception. Types not
                // deriving from DispatcherObject are allowed - it is up to the user to
                // make any custom types free-threaded.

View on GitHub (pinned to 81131a70a4)