dotnet/maui · error · XamlParseException
Expected {nameof(VisualStateGroupList)} but found {parents[3
Error message
Expected {nameof(VisualStateGroupList)} but found {parents[3]}. What it means
XamlParseException raised in FindTypeForVisualState when parents[3] (after the VisualStateGroup was confirmed) is neither a VisualElement (direct visual states) nor a VisualStateGroupList. The only two valid containers for a VisualStateGroup are a VisualStateGroupList (under a Style) or a VisualElement directly; anything else is a structural error.
Source
Thrown at src/Controls/src/Core/BindablePropertyConverter.cs:143
=> type.GetField(fieldName, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
Type FindTypeForVisualState(IProvideParentValues parentValueProvider, IXmlLineInfo lineInfo)
{
var parents = parentValueProvider.ParentObjects.ToList();
// Skip 0; we would not be making this check if TargetObject were not a Setter
// Skip 1; we would not be making this check if the immediate parent were not a VisualState
// VisualStates must be in a VisualStateGroup
if (parents[2] is not VisualStateGroup)
throw new XamlParseException($"Expected {nameof(VisualStateGroup)} but found {parents[2]}.", lineInfo);
// Are these Visual States directly on a VisualElement?
if (parents[3] is VisualElement vsTarget)
return vsTarget.GetType();
if (parents[3] is not VisualStateGroupList)
throw new XamlParseException($"Expected {nameof(VisualStateGroupList)} but found {parents[3]}.", lineInfo);
if (parents[4] is VisualElement veTarget)
return veTarget.GetType();
if (parents[4] is not Setter)
throw new XamlParseException($"Expected {nameof(Setter)} but found {parents[4]}.", lineInfo);
if (parents[5] is TriggerBase trigger)
return trigger.TargetType;
// These must be part of a Style; verify that
if (parents[5] is Style style)
return style.TargetType;
throw new XamlParseException($"Unable to find a TragetType for the Bindable Property. Try prefixing it with the TargetType.", lineInfo);
}
View on GitHub (pinned to f377ff1c5e)
Solutions
- If the group lives under a Style, wrap it in a VisualStateGroupList.
- If it lives directly on an element, ensure that element is a VisualElement.
- Match the documented parent chain for the Style vs direct-element cases.
Example fix
<!-- before -->
<Style><VisualStateGroup> ... </VisualStateGroup></Style>
<!-- after -->
<Style>
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup> ... </VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
</Style> Defensive patterns
Strategy: validation
Validate before calling
// In a Style, wrap VisualStateGroup in a VisualStateGroupList under // VisualStateManager.VisualStateGroups.
Try / catch
try { /* compile */ }
catch (XamlParseException ex) when (ex.Message.Contains("VisualStateGroupList"))
{
// prompt author to add the VisualStateGroupList wrapper
} Prevention
- Distinguish the direct-element vs Style cases for visual states.
- Use the canonical nesting from the docs.
When it happens
Trigger: Placing a VisualStateGroup under a non-VisualElement and non-VisualStateGroupList parent; a malformed Style whose Setters/VisualStateGroups are mis-nested; custom containers used as visual-state hosts.
Common situations: Editing a Style's VisualStateManager section and dropping the VisualStateGroupList wrapper; putting visual states on a non-visual element.
Related errors
- Expected {nameof(VisualStateGroup)} but found {parents[2]}.
- Expected {nameof(Setter)} but found {parents[4]}.
- Unable to find a TragetType for the Bindable Property. Try p
- Can't resolve {0}
- Can't resolve {parts[0]}
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/5423d5f2b6d9674f.
Report an issue: GitHub.