microsoft / microsoft/microsoft-ui-xaml

Duplicate ListView items hang the UI thread on any UI-Automation tree walk (UiaNodeTraverser sibling cycle)

Open
#11,226 0 comments 0 reactions 0 assignees View on GitHub
area-Accessibility bug team-Controls
Dominant language
C++
Stars
8.4k
Forks
942
Avg merge
2d 7h
Merged PRs (30d)
105

Description

### Describe the bug

A `ListView` (or any `ItemsControl`) whose `ItemsSource` contains two or more **equal** items
(`Object.Equals` returns `true`) hangs its **UI thread** the first time any UI-Automation client
walks the element tree. The UI thread spins forever inside
`UIAutomationCore.dll!UiaNodeTraverser::GetNextSibling` servicing an in-process `UiaNode_Find`,
because the ListView's automation peers report a **cyclic sibling chain** for the duplicated
items. There is no crash and no exception — the window simply stops responding and the UI
thread pins a core at 100%. The app is fully healthy until that first automation walk.

Changing only the item strings to be distinct removes the hang completely.

### Why is this important?

This strands assistive-technology users: **Narrator** walking any list that happens to contain
repeated text (duplicate labels, repeated statuses, same file name in two folders) freezes the
whole app. It also hangs any UI-test framework — I hit it originally with FlaUI in an automated
test suite, where every run wedged the app under test. Because it is a UI-thread hang rather
than a handled error, there is no recovery and no diagnostic; the app just becomes unresponsive.

Microsoft's documentation warns that duplicate items break UI Automation, but only for **WPF**,
and only as *degraded* behavior (later duplicates are hidden), not a hang:

> Certain features of UI Automation do not work correctly when an `ItemsControl` contains
> duplicate objects. If an object appears multiple times, only the first instance appears in
> the automation tree. (Two objects *x* and *y* are considered to be duplicates if
> `Object.Equals(x, y)` returns `true`.)
> — https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.itemscontrol#remarks

On WinUI 3 the same input hangs the UI thread instead of degrading, and the WinUI docs don't
mention the limitation at all.

### Steps to reproduce the bug

Minimal, self-contained repro attached (a WinUI 3 app + a UI-Automation driver + a script that
proves the freeze by polling a UI-thread heartbeat while the walk runs):

[winui-duplicate-items-uia-hang-repro.zip](https://github.com/user-attachments/files/29764978/winui-duplicate-items-uia-hang-repro.zip)

The essence is a ListView bound to identical strings:

```csharp
var items = new List();
for (var i = 0; i < 6; i++)
items.Add("duplicate row"); // identical strings -> hang
// items.Add($"row {i}"); // distinct strings -> fine
_list.ItemsSource = items;
```

1. Show a window whose `ListView` is filled with the duplicate strings (items must be realized/
visible; a short, fully-visible list on the default virtualizing panel is enough).
2. From any UIA client, walk the tree — e.g. `FindAllDescendants()` (FlaUI),
`AutomationElement.FindAll(TreeScope.Descendants, Condition.TrueCondition)`, or simply run
Narrator over the list.
3. The client call never returns and the app's UI thread hangs.

Repro output — duplicate mode, heartbeat frozen at a single value across 10 seconds of walking:

```
App healthy - heartbeat advancing ('UI heartbeat: 5 (21:47:09.112)').
driver: HANG CONFIRMED - FindAllDescendants did not return within 15s.
Heartbeat samples during the walk: UI heartbeat: 6 (21:47:09.375)
-> 1 distinct value(s) across 10 seconds of walking.
```

Unique mode — identical code, distinct strings, no hang:

```
driver: OK - FindAllDescendants returned 25 elements in 12 ms. No hang.
-> 10 distinct value(s) across 10 seconds of walking.
```

### Actual behavior

The UI thread spins forever in `UiaNodeTraverser` and the app becomes unresponsive; the UIA
client's walk never returns.

Native call stack of the app's UI thread while the client's `FindAll` is in flight
(mixed-mode debugger):

```
Microsoft.ui.xaml.dll!DirectUI::DependencyObject::CheckThread()
Microsoft.ui.xaml.dll!DirectUI::FrameworkElementAutomationPeer::IsControlElementCore(...)
Microsoft.ui.xaml.dll!CUIAWrapper::GetPropertyValue(...)
UIAutomationCore.dll!UiaNode::ProviderGetPropertyValue(...)
UIAutomationCore.dll!InProcClientAPIStub::UiaNode_GetPropertyValues(...)
UIAutomationCore.dll!FindingVisitor::Enter(...)
UIAutomationCore.dll!UiaNodeTraverser::Traverse(...) <-- does not terminate
UIAutomationCore.dll!InProcClientAPIStub::UiaNode_Find(...)
UIAutomationCore.dll!RemoteUiaNodeStub::Incoming_Find(...)
... RPC from the out-of-process client ...
Microsoft.ui.xaml.dll!DirectUI::FrameworkApplication::RunDesktopWindowMessageLoop()
```

### Expected behavior

A UI-Automation tree walk completes. Duplicate items may degrade gracefully (as documented for
WPF — e.g. later duplicates collapse in the tree), but the UI thread must never hang.

### Screenshots

N/A — the failure is a UI-thread hang. The attached repro's `run.ps1` demonstrates it
programmatically by polling a UI-thread heartbeat that freezes for the entire walk.

### NuGet package version

Microsoft.WindowsAppSDK 2.2.0 latest stable WinUI 3

### Windows version

_No response_

### Additional context

Windows 11, OS build 10.0.26200. Also reproduces on
1.7.250909003. Microsoft.Windows.SDK.BuildTools 10.0.28000.2270; TargetFramework
net10.0-windows10.0.26100.0, unpackaged, win-x64.

- Cause confirmed by bisection: distinct item strings never hang; identical strings hang
deterministically. Six identical strings are enough.
- **Not** fixed by mitigations that leave the duplicates in place: custom item templates,
explicit `AutomationProperties.Name`, a non-virtualizing items panel, swapping `ItemsSource`,
or rebuilding the `ListView`. Only making the items distinct fixes it.
- **Workaround:** ensure every item bound to an `ItemsControl` is distinct — unique strings or
wrapper objects with reference identity.
- I searched the existing issues before filing and did not find this specific duplicate-item
UI-thread hang reported.
- UIA client used to reproduce: FlaUI.UIA3 5.0.0 (wraps `CUIAutomation`); Narrator reproduces
it too.

> **Disclaimer:** This issue was diagnosed and the reproduction was authored with the help of
> an AI coding assistant. The root cause, the minimal repro, and the results above were
> reviewed and verified by a human on real hardware before filing.

Contributor guide

Open the contributing guide

Research direction

Start with the attached winui-duplicate-items-uia-hang-repro.zip and its run.ps1, comparing duplicate and distinct ListView items while polling the heartbeat. Trace the UiaNode_Find path and the reported UiaNodeTraverser::GetNextSibling entry point, focusing on the ListView automation peers. Done means a UI-Automation tree walk completes without freezing the UI thread for duplicate items.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, csharp
Domain
accessibility, desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.