microsoft / microsoft/microsoft-ui-xaml
Duplicate ListView items hang the UI thread on any UI-Automation tree walk (UiaNodeTraverser sibling cycle)
- 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
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