dotnet/wpf · error · InvalidOperationException

SR.InavalidStartItem

Error message

SR.InavalidStartItem

What it means

DataGridColumnHeadersPresenterAutomationPeer.GetChildrenCore throws InvalidOperationException when the caller passes a startAfterItem automation peer whose underlying Column is null. The peer cannot compute the start index for partial children enumeration, so the operation is rejected as the start item is not backed by a real column.

Solutions

  1. Ensure the startAfterItem peer comes from a current GetChildren/FindItemByProperty result and still maps to a live DataGridColumn.
  2. Check startAfterItem.Column != null before passing it as the anchor.
  3. Catch InvalidOperationException and fall back to enumerating children from the start (pass null anchor).
  4. Avoid caching column-header automation peers across column collection changes.

Example fix

// before
var anchor = stalePeer; // Column == null after column removal
var item = presenter.FindItemByProperty(anchor, propertyId, value);
// after
if (anchor?.Column != null)
    item = presenter.FindItemByProperty(anchor, propertyId, value);
else
    item = presenter.FindItemByProperty(null, propertyId, value);
Defensive patterns

Strategy: validation

Validate before calling

if (anchor == null || anchor.Column == null)
    anchor = null; // search from start instead of using invalid anchor

Type guard

bool IsValidAnchor(AutomationPeer p) => p is DataGridColumnHeaderAutomationPeer ch && ch.Column != null;

Try / catch

try { return container.FindItemByProperty(anchor, propertyId, value); }
catch (InvalidOperationException) { return container.FindItemByProperty(null, propertyId, value); }

Prevention

When it happens

Trigger: Calling UIA FindItemByProperty / IItemContainerProvider.FindItemByProperty on the column-headers presenter and passing a startAfterItem peer whose .Column property is null (e.g. a detached or virtualized column-header peer).

Common situations: UIA clients (inspect.exe, test automation frameworks, screen readers) holding a stale automation peer after a DataGrid column was removed or re-created, then using it as the search anchor.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Automation/Peers/DataGridColumnHeadersPresenterAutomationPeer.cs:185

            if (items != null && items.Count > 0)
            {
                DataGridColumnHeaderItemAutomationPeer startAfterItem = null;
                if (startAfter != null)
                {
                    // get the peer corresponding to this provider
                    startAfterItem = PeerFromProvider(startAfter) as DataGridColumnHeaderItemAutomationPeer;
                    if (startAfterItem == null)
                        return null;
                }

                // startIndex refers to the index of the item just after startAfterItem
                int startIndex = 0;
                if (startAfterItem != null)
                {
                    if (startAfterItem.Item == null)
                    {
                        throw new InvalidOperationException(SR.InavalidStartItem);
                    }

                    // To find the index of the column items collection which occurs
                    // immidiately after startAfterItem.Item
                    startIndex = items.IndexOf(startAfterItem.Column) + 1;
                    if (startIndex == 0 || startIndex == items.Count)
                        return null;
                }

                if (propertyId == 0)
                {
                    for (int i = startIndex; i < items.Count; i++)
                    {
                        // This is to handle the case of when dataItems are just plain strings and have duplicates,
                        // only the first occurence of duplicate Items will be returned. It has also been used couple more times below.
                        if (items.IndexOf(items[i]) != i)
                            continue;
                        return (ProviderFromPeer(FindOrCreateItemAutomationPeer(items[i])));

View on GitHub (pinned to 81131a70a4)