dotnet/wpf · error · ElementNotEnabledException

ElementNotEnabledException

Error message

ElementNotEnabledException

What it means

ButtonAutomationPeer implements IInvokeProvider.Invoke, which UI Automation clients call to programmatically 'click' a button. If the button's IsEnabled() returns false, the peer throws ElementNotEnabledException, as required by the UIA provider contract, signaling that the Invoke pattern action cannot be performed on a disabled element.

Solutions

  1. Wait for the button to become enabled: subscribe to AutomationPropertyChangedEvent for IsEnabledProperty == true or poll before invoking.
  2. Use a retry/wait helper in the test framework instead of invoking immediately.
  3. Fix test timing so the UI state that enables the button is reached first (e.g. fill required fields via ValuePattern).
  4. Wrap Invoke() in try/catch for ElementNotEnabledException and retry after a delay if the disable is transient.

Example fix

// before
var pattern = (InvokePattern)button.GetCurrentPattern(InvokePattern.Pattern);
pattern.Invoke(); // throws if disabled
// after
if ((bool)button.GetCurrentPropertyValue(AutomationElement.IsEnabledProperty))
{
    ((InvokePattern)button.GetCurrentPattern(InvokePattern.Pattern)).Invoke();
}
Defensive patterns

Strategy: validation

Validate before calling

bool isEnabled = (bool)button.GetCurrentPropertyValue(AutomationElement.IsEnabledProperty);
if (!isEnabled) throw new InvalidOperationException("Button is disabled; do not Invoke.");

Type guard

bool CanInvoke(AutomationElement el) =>
    (bool)el.GetCurrentPropertyValue(AutomationElement.IsEnabledProperty) &&
    el.GetSupportedPatterns().Any(p => p.Pattern == InvokePattern.Pattern);

Try / catch

try { ((InvokePattern)button.GetCurrentPattern(InvokePattern.Pattern)).Invoke(); }
catch (ElementNotEnabledException)
{
    // wait for IsEnabled == true, then retry
}

Prevention

When it happens

Trigger: A UI Automation client (test framework, screen reader, automation script) retrieves the InvokePattern of a Button whose IsEnabled is false and calls Invoke() — typically clicking a button disabled because form data is invalid or an async operation is in progress.

Common situations: Coded UI / UIA test suites racing against buttons disabled during loading; automation scripts running before data binding enables the button; accessibility clients invoking controls on a disabled form.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Automation/Peers/ButtonAutomationPeer.cs:41

        ///
        protected override AutomationControlType GetAutomationControlTypeCore()
        {
            return AutomationControlType.Button;
        }

        /// 
        public override object GetPattern(PatternInterface patternInterface)
        {
            if (patternInterface == PatternInterface.Invoke)
                return this;
            else
                return base.GetPattern(patternInterface);
        }

        void IInvokeProvider.Invoke()
        {
            if(!IsEnabled())
                throw new ElementNotEnabledException();

            // Async call of click event
            // In ClickHandler opens a dialog and suspend the execution we don't want to block this thread
            Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(delegate(object param)
            {
                ((Button)Owner).AutomationButtonBaseClick();
                return null;
            }), null);
        }
    }
}

View on GitHub (pinned to 81131a70a4)