dotnet/wpf · error · ArgumentException

SR.Format(SR.PropertyConditionIncorrectType…

Error message

SR.Format(SR.PropertyConditionIncorrectType, property.ProgrammaticName, expectedType.Name)

What it means

The PropertyCondition constructor checks that the condition value's type matches the property's expected type: null is rejected for value-type properties, and the value's runtime type must be assignable to the expected type. On mismatch it throws ArgumentException naming the property's programmatic name and the expected type.

Solutions

  1. Coerce the value to the expected type before constructing (Convert.ChangeType with the property's expected type)
  2. Use proper enum values (e.g. DockPosition.Top) instead of strings
  3. Pass AutomationElement.NotSupported only where semantics allow it, not null for value types
  4. Centralize condition building in a helper that validates value types

Example fix

// before
var cond = new PropertyCondition(AutomationElement.IsOffscreenProperty, "false"); // string vs bool
// after
var cond = new PropertyCondition(AutomationElement.IsOffscreenProperty, false);
Defensive patterns

Strategy: validation

Validate before calling

object Coerce(AutomationProperty p, object v) => v switch {
    null or object _ when v == AutomationElement.NotSupported => v,
    string s when p == AutomationElement.IsOffscreenProperty => bool.Parse(s),
    string s when double.TryParse(s, out var d) => d,
    _ => v };

Type guard

bool TypeOk(Type expected, object v) => v == AutomationElement.NotSupported || (v == null ? !expected.IsValueType : expected.IsInstanceOfType(v));

Try / catch

try { cond = new PropertyCondition(p, v); } catch (ArgumentException ex) { /* log p.ProgrammaticName; coerce or skip */ }

Prevention

When it happens

Trigger: new PropertyCondition(boolProperty, "true"); new PropertyCondition(numericProperty, null); passing a string value for a double/enum/int property in FindAll/FindFirst conditions.

Common situations: Values sourced from UI text boxes or configuration as strings; JSON-deserialized values of indeterminate type; switching a property whose expected type changed between UIA versions; accidentally passing the wrong enum type (e.g. DockPosition as string).

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClient/System/Windows/Automation/PropertyCondition.cs:138

        private void Init(AutomationProperty property, object val, PropertyConditionFlags flags )
        {
            ArgumentNullException.ThrowIfNull(property);

            AutomationPropertyInfo info;
            if (!Schema.GetPropertyInfo(property, out info))
            {
                throw new ArgumentException(SR.UnsupportedProperty);
            }

            // Check type is appropriate: NotSupported is allowed against any property,
            // null is allowed for any reference type (ie not for value types), otherwise
            // type must be assignable from expected type.
            Type expectedType = info.Type;
            if (val != AutomationElement.NotSupported &&
                ((val == null && expectedType.IsValueType)
                || (val != null && !expectedType.IsAssignableFrom(val.GetType()))))
            {
                throw new ArgumentException(SR.Format(SR.PropertyConditionIncorrectType, property.ProgrammaticName, expectedType.Name));
            }

            if ((flags & PropertyConditionFlags.IgnoreCase) != 0)
            {
                Misc.ValidateArgument(val is string, nameof(SR.IgnoreCaseRequiresString));
            }

            // Some types are handled differently in managed vs unmanaged - handle those here...
            if (val is AutomationElement)
            {
                // If this is a comparison against a Raw/LogicalElement,
                // save the runtime ID instead of the element so that we
                // can take it cross-proc if needed.
                val = ((AutomationElement)val).GetRuntimeId();
            }
            else if (val is ControlType)
            {
                // If this is a control type, use the ID, not the CLR object

View on GitHub (pinned to 81131a70a4)