dotnet/wpf · warning · InvalidOperationException

SR.Format(SR.UnexpectedValueTypeForDataTrigger…

Error message

SR.Format(SR.UnexpectedValueTypeForDataTrigger, propertyValue.ValueType)

What it means

DataTrigger.Seal throws InvalidOperationException when it encounters a PropertyValueType in its property values it does not recognize while converting to the DataTrigger form. This is an internal invariant check — only PropertyTrigger and PropertyTriggerResource are legal here. Hitting it means internal property-engine state was corrupted or a new value type was added without updating DataTrigger.

Solutions

  1. Check that property values were only created through the public style/trigger APIs
  2. Review PropertyValueType values produced upstream (StyleHelper / property engine) for a case missing from DataTrigger.Seal
  3. Report as a WPF framework bug if reproduced with public API only
Defensive patterns

Strategy: try-catch

Try / catch

try { trigger.Seal(); } catch (InvalidOperationException ex) { Debug.Fail($"Internal PropertyValueType corruption: {ex.Message}"); }

Prevention

When it happens

Trigger: Internal sealing pipeline encountering an unexpected PropertyValueType enum value in PropertyValues; usually not reachable from public API without framework-internal misuse.

Common situations: Running modified/reflected internal WPF code; third-party libraries poking at internal property-engine structures; WPF version mismatches.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/DataTrigger.cs:174

                    LogicalOp.Equals,
                    _value) };

            // Set Condition for all data triggers
            for (int i = 0; i < PropertyValues.Count; i++)
            {
                PropertyValue propertyValue = PropertyValues[i];

                propertyValue.Conditions = TriggerConditions;
                switch (propertyValue.ValueType)
                {
                    case PropertyValueType.Trigger:
                        propertyValue.ValueType = PropertyValueType.DataTrigger;
                        break;
                    case PropertyValueType.PropertyTriggerResource:
                        propertyValue.ValueType = PropertyValueType.DataTriggerResource;
                        break;
                    default:
                        throw new InvalidOperationException(SR.Format(SR.UnexpectedValueTypeForDataTrigger, propertyValue.ValueType));
                }

                // Put back modified struct
                PropertyValues[i] = propertyValue;
            }

            base.Seal();
        }

        // evaluate the current state of the trigger
        internal override bool GetCurrentState(DependencyObject container, UncommonField<HybridDictionary[]> dataField)
        {
            Debug.Assert( TriggerConditions != null && TriggerConditions.Length == 1,
                "This method assumes there is exactly one TriggerCondition." );

            return TriggerConditions[0].ConvertAndMatch(StyleHelper.GetDataTriggerValue(dataField, container, TriggerConditions[0].Binding));
        }

View on GitHub (pinned to 81131a70a4)