dotnet/wpf · error · InvalidOperationException

InvalidOperationException (no message)

Error message

InvalidOperationException (no message)

What it means

VisualStateManager.GoToStateInternal transitions a control to a named VisualState. If the supplied state belongs to no VisualStateGroup known to this VisualStateManager (group == null), the framework throws a bare InvalidOperationException indicating an internal lookup failure - the state's group could not be resolved for the given stateGroupsRoot. It signals the state/group topology does not match what the caller passed.

Solutions

  1. Verify the control template defines a VisualStateManager.VisualStateGroups element containing the state group and state name used in GoToState
  2. Ensure state names in code exactly match XAML state names (case-sensitive)
  3. If GoToState returned false previously, check the template was applied (ApplyTemplate) before transitioning
  4. Restructure so states live inside proper VisualStateGroup containers
Defensive patterns

Strategy: validation

Validate before calling

var groups = VisualStateManager.GetVisualStateGroups(root);
if (!groups.Any(g => g.States.Any(s => s.Name == stateName))) return false;

Type guard

bool StateExists(FrameworkElement root, string name) =>
    VisualStateManager.GetVisualStateGroups(root)?.OfType<VisualStateGroup>()
        .Any(g => g.States.OfType<VisualState>().Any(s => s.Name == name)) == true;

Try / catch

try { VisualStateManager.GoToState(control, stateName, true); } catch (InvalidOperationException) { /* template not applied or state missing; defer until loaded */ }

Prevention

When it happens

Trigger: Calling VisualStateManager.GoToState(control, stateName, useTransitions) where the state name exists but its VisualStateGroup cannot be located on the control's template root, or calling GoToStateCore with mismatched group/state arguments.

Common situations: Template VSM tree out of sync with the code-behind state names after renaming states; control template lacks the expected VisualStateGroup; custom controls calling GoToState with states not defined in the template's VisualStateManager.VisualStateGroups.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/VisualStateManager.cs:192

                    group = g;
                    state = s;
                    return true;
                }
            }

            group = null;
            state = null;
            return false;
        }

        private static bool GoToStateInternal(FrameworkElement control, FrameworkElement stateGroupsRoot, VisualStateGroup group, VisualState state, bool useTransitions)
        {
            ArgumentNullException.ThrowIfNull(stateGroupsRoot);
            ArgumentNullException.ThrowIfNull(state);

            if (group == null)
            {
                throw new InvalidOperationException();
            }

            VisualState lastState = group.CurrentState;
            if (lastState == state)
            {
                return true;
            }

            // Get the transition Storyboard. Even if there are no transitions specified, there might
            // be properties that we're rolling back to their default values.
            VisualTransition transition = useTransitions ? VisualStateManager.GetTransition(stateGroupsRoot, group, lastState, state) : null;

            // Generate dynamicTransition Storyboard
            Storyboard dynamicTransition = GenerateDynamicTransitionAnimations(stateGroupsRoot, group, state, transition);

            // If the transition is null, then we want to instantly snap. The dynamicTransition will
            // consist of everything that is being moved back to the default state.
            // If the transition.Duration and explicit storyboard duration is zero, then we want both the dynamic 

View on GitHub (pinned to 81131a70a4)