dotnet/wpf · error · InvalidOperationException

UIA_OperationCannotBePerformed

Error message

UIA_OperationCannotBePerformed

What it means

RibbonMenuButtonAutomationPeer.Collapse (the IExpandCollapseProvider implementation) throws InvalidOperationException(SR.UIA_OperationCannotBePerformed) when the owning RibbonMenuButton has no items. Collapsing a dropdown that contains nothing is rejected as an unsupported UIA operation. An ElementNotEnabledException is thrown earlier if the control is disabled.

Solutions

  1. Before Collapse, check owner.HasItems (or that the automation peer's children exist) and skip the call when empty.
  2. Guard the pattern availability: only collapse when ExpandCollapseState is Expanded and the button has items.
  3. Bind/verify that the RibbonMenuButton's ItemsSource is populated before exposing the control to UIA scenarios.
  4. Catch InvalidOperationException around Collapse and treat empty menus as a no-op rather than a test failure.

Example fix

// before
expandCollapsePattern.Collapse(); // throws when no items
// after
var menuButton = (RibbonMenuButton)targetControl;
if (menuButton.HasItems && menuButton.IsDropDownOpen)
    expandCollapsePattern.Collapse();
Defensive patterns

Strategy: validation

Validate before calling

var menuButton = (RibbonMenuButton)targetControl;
bool canCollapse = menuButton.HasItems && menuButton.IsDropDownOpen;

Type guard

bool CanCollapse(RibbonMenuButton b) => b != null && b.HasItems;

Try / catch

try { expandCollapsePattern.Collapse(); }
catch (InvalidOperationException)
{
    // empty or already-closed menu — treat as no-op
}

Prevention

When it happens

Trigger: UIA client calling ExpandCollapsePattern.Collapse on a RibbonMenuButton whose Items/HasItems is empty — e.g. all items were removed, data binding produced no entries, or the button is a placeholder before items load.

Common situations: Test suites that collapse every discovered menu button indiscriminately, hitting item-less buttons; apps whose Ribbon menu content is populated asynchronously or per user role and starts empty; telemetry/accessibility tools traversing the Ribbon tree.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Windows.Controls.Ribbon/Microsoft/Windows/Automation/Peers/RibbonMenuButtonAutomationPeer.cs:172

                if ((OwningMenuButton.CanUserResizeHorizontally || OwningMenuButton.CanUserResizeVertically) 
                    && OwningMenuButton.IsDropDownOpen)
                    return this;
            }

            return base.GetPattern(patternInterface);
        }

        #region IExpandCollapseProvider Members

        void IExpandCollapseProvider.Collapse()
        {
            if (!IsEnabled())
                throw new ElementNotEnabledException();

            RibbonMenuButton owner = OwningMenuButton;
            if (!owner.HasItems)
            {
                throw new InvalidOperationException(Microsoft.Windows.Controls.SR.UIA_OperationCannotBePerformed);
            }

            owner.IsDropDownOpen = false;
        }

        void IExpandCollapseProvider.Expand()
        {
            if (!IsEnabled())
                throw new ElementNotEnabledException();

            RibbonMenuButton owner = OwningMenuButton;
            if (!owner.HasItems)
            {
                throw new InvalidOperationException(Microsoft.Windows.Controls.SR.UIA_OperationCannotBePerformed);
            }

            owner.IsDropDownOpen = true;
        }

View on GitHub (pinned to 81131a70a4)