dotnet/wpf · warning · ElementNotAvailableException

SR.VirtualizedElement

Error message

SR.VirtualizedElement

What it means

ItemAutomationPeer.ThrowElementNotAvailableException throws ElementNotAvailableException(SR.VirtualizedElement) when UIA queries a peer whose item is virtualized (not realized in the automation tree). This only fires when the VirtualizedItem pattern is available, the peer is not a GridViewItemAutomationPeer, and the peer is not attached to its parent's children. It signals the client that the element must be realized (e.g. via ScrollItemPattern.ScrollIntoView) before it can be used.

Solutions

  1. Call VirtualizedItemPattern.Realize() (or ScrollItemPattern.ScrollIntoView()) on the element before reading its properties.
  2. Scroll the container into view in the app (BringIntoView) or disable UI virtualization if the list is small (VirtualizingStackPanel.VirtualizationMode / ScrollViewer.CanContentScroll=false).
  3. In UIA clients, treat UIA_E_ELEMENTNOTAVAILABLE as a cue to realize/scroll and retry.
  4. Catch ElementNotAvailableException in code that iterates ItemsControl items and skip or realize the item.

Example fix

// before
var name = listItem.Current.Name; // may throw element-not-available
// after
var virt = listItem.GetCurrentPattern(VirtualizedItemPattern.Pattern) as VirtualizedItemPattern;
virt?.Realize();
var name = listItem.Current.Name;
Defensive patterns

Strategy: try-catch

Validate before calling

if (element.GetCurrentPattern(VirtualizedItemPattern.Pattern) is VirtualizedItemPattern v) v.Realize();

Type guard

static bool IsAvailable(AutomationElement e) => !e.Current.IsOffscreen || e.TryGetCurrentPattern(VirtualizedItemPattern.Pattern, out _);

Try / catch

try { ReadElementProperties(item); } catch (ElementNotAvailableException) { item.GetPattern(VirtualizedItemPattern).Realize(); ReadElementProperties(item); }

Prevention

When it happens

Trigger: UIA client accesses properties or patterns of an item in a virtualized ItemsControl (ListBox/ListView/DataGrid with virtualization on) while the item is scrolled out of view and not in the automation tree.

Common situations: UIA tests addressing list items by index in large lists without scrolling the item into view; older/unpatched UIA clients that don't handle VirtualizedItem pattern; accessing DataGrid rows in virtualization modes after data changes.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Automation/Peers/ItemAutomationPeer.cs:125

                if(wrapperPeer == null) //fall back to default peer if there is no specific one
                {
                    if(wrapper is FrameworkElement)
                        wrapperPeer = new FrameworkElementAutomationPeer((FrameworkElement)wrapper);
                    else
                        wrapperPeer = new UIElementAutomationPeer(wrapper);
                }
            }

            return wrapperPeer;
        }

        /// <summary>
        internal void ThrowElementNotAvailableException()
        {
            // To avoid the situation on legacy systems which may not have new unmanaged core. this check with old unmanaged core
            // avoids throwing exception and provide older behavior returning default values for items which are virtualized rather than throwing exception.
            if (VirtualizedItemPatternIdentifiers.Pattern != null && !(this is GridViewItemAutomationPeer) && !IsItemInAutomationTree())
                throw new ElementNotAvailableException(SR.VirtualizedElement);
        }

        private bool IsItemInAutomationTree()
        {
            AutomationPeer parent = this.GetParent();
            if(this.Index != -1 && parent != null && parent.Children != null && this.Index < parent.Children.Count && parent.Children[this.Index] == this)
                return true;
            else return false;
        }


        ///
        internal override bool IgnoreUpdatePeer()
        {
            // Ignore UpdatePeer if the we're no longer in the automation tree.
            // There's no need to update such a peer, as it no longer
            // participates in automation.  And UpdatePeer actually throws exceptions
            // in some cases.

View on GitHub (pinned to 81131a70a4)