dotnet/wpf · error · InvalidOperationException

SR.InavalidStartItem

Error message

SR.InavalidStartItem

What it means

DataGridItemAutomationPeer.FindItemByProperty throws InvalidOperationException when startAfterItem is provided but its Column is null, so the peer cannot determine the index in the columns collection at which to start searching. Only column-header peers with a live column can act as the anchor.

Solutions

  1. Verify startAfterItem.Column != null before using it as an anchor.
  2. Refresh the anchor peer from a fresh FindItemByProperty/GetChildren call after any column change.
  3. Pass null as startAfterItem to search from the beginning.
  4. Catch InvalidOperationException and restart the search without an anchor.

Example fix

// before
var found = rowPeer.FindItemByProperty(badAnchor, 0, null); // badAnchor.Column == null
// after
var found = (badAnchor?.Column != null)
    ? rowPeer.FindItemByProperty(badAnchor, 0, null)
    : rowPeer.FindItemByProperty(null, 0, null);
Defensive patterns

Strategy: validation

Validate before calling

if (anchor != null && anchor.Column == null)
    anchor = null; // restart search from beginning

Type guard

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

Try / catch

try { return peer.FindItemByProperty(anchor, 0, value); }
catch (InvalidOperationException) { return peer.FindItemByProperty(null, 0, value); }

Prevention

When it happens

Trigger: Calling FindItemByProperty on a DataGridItemPeer (row) passing a startAfterItem peer whose Column property is null — e.g. a peer for a removed/virtualized column or a non-column peer passed by mistake.

Common situations: Stale UIA anchors after columns are regenerated; mixing row peers and column peers as anchors; virtualization dropping the underlying column reference.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Automation/Peers/DataGridItemAutomationPeer.cs:157

            IList<DataGridColumn> columns = OwningDataGrid.Columns;

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

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

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

                if (propertyId == 0 && startIndex < columns.Count)
                {
                    return (ProviderFromPeer(GetOrCreateCellItemPeer(columns[startIndex])));
                }

                DataGridCellItemAutomationPeer currentItemPeer;
                object currentValue = null;
                for (int i = startIndex; i < columns.Count; i++)
                {

View on GitHub (pinned to 81131a70a4)