microsoft / microsoft/microsoft-ui-xaml
ItemsView crashes with E_INVALIDARG when a pending bring-into-view target is collapsed
- Dominant language
- C++
- Stars
- 8.4k
- Forks
- 942
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 105
Description
### Describe the bug
`ItemsView.StartBringItemIntoView` retains its target in `m_bringIntoViewElement`. If that item subsequently becomes collapsed, a later layout pass can cause `ItemsView` to submit that now-invalid element as the scroll anchor. `ScrollingAnchorRequestedEventArgs::AnchorElement` throws `E_INVALIDARG`, and the application terminates with a stowed exception.
The minimal reproduction below uses only WinUI controls and two items. It does **not** require Reactor, OpenClaw, a gateway, Markdown rendering, or a large data set. An explicit `UpdateLayout()` call is **not required**.
### Why is this important?
I encountered this crash while investigating session/history navigation in OpenClaw: [openclaw/openclaw-windows-node#1167](https://github.com/openclaw/openclaw-windows-node/issues/1167).
Switching back and forth between large chat sessions can crash during automatic bottom-positioning. A bring target may become invalid as the displayed rows change. I manually confirmed that the simple reproduction reaches the same failing native code path as the OpenClaw crash.
This report specifically concerns the confirmed invalid-anchor **crash**. The linked OpenClaw issue also discusses a CPU-bound hang; this report does not establish that the hang has the same cause.
### Steps to reproduce the bug
1. Create a blank C# WinUI 3 app using `Microsoft.WindowsAppSDK` **2.4.0**. The example below assumes the project namespace is `ReproApp`.
2. Replace `MainWindow.xaml` and `MainWindow.xaml.cs` with the following.
3. Run the app and click **Reproduce crash** once.
4. The next layout pass throws. For synchronous debugger stepping, optionally uncomment the `UpdateLayout()` call.
**MainWindow.xaml**
```xml
```
**MainWindow.xaml.cs**
```csharp
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace ReproApp;
public sealed partial class MainWindow : Window
{
private readonly ItemContainer _target = new()
{
Height = 100,
Child = new TextBlock { Text = "Target" },
};
public MainWindow()
{
InitializeComponent();
Items.ItemsSource = new[]
{
new ItemContainer { Height = 2000, Child = new TextBlock { Text = "First item" } },
_target,
};
}
private void OnReproduce(object sender, RoutedEventArgs args)
{
Items.StartBringItemIntoView(1, new BringIntoViewOptions { AnimationDesired = false });
_target.Visibility = Visibility.Collapsed;
// Optional: makes the failure synchronous for debugger stepping.
// Items.UpdateLayout();
}
}
```
### Actual behavior
- `E_INVALIDARG` / `0x80070057`: "The parameter is incorrect."
- With explicit `UpdateLayout()`, the exception is surfaced as `System.ArgumentException` at that call.
- Without explicit `UpdateLayout()`, the failure occurs during the normal deferred layout pass.
- The process terminates with native stowed exception `0xC000027B`.
### Expected behavior
Collapsing an item during a pending bring-into-view operation should cancel or invalidate the pending target, or allow selection of another eligible anchor. It should not cause an unhandled exception during layout.
### NuGet package version
- `Microsoft.WindowsAppSDK`: **2.4.0**
- Loaded native `Microsoft.UI.Xaml.dll`: **3.2.3.2608**
- Native binary source revision: `aa188bfdf74608810e8e57228db6dd137f4e74e4`
- `Microsoft.Windows.SDK.BuildTools`: **10.0.28000.2705**
- Repro target framework: `net10.0-windows10.0.26100.0`
- .NET runtime: **10.0.12**
### Windows version
Windows 11 Enterprise (25H2), build **26200**, ARM64.
### Additional context
Note that the reproducer is a narrowed-down simplified version that triggers the same callstack, but the actual failure-case in OpenClaw to get to this point is more complicated - the collapsing of the view is just a more reliable/simple way to trigger the behavior.
Matching native PDBs and stowed-exception stacks identify the following relevant frames (WinRT forwarding frames omitted):
```text
ScrollingAnchorRequestedEventArgs::AnchorElement
ScrollingAnchorRequestedEventArgs.cpp:43, throws E_INVALIDARG
ItemsView::OnScrollViewAnchorRequested
ItemsView.cpp:972, passes m_bringIntoViewElement to args.AnchorElement(...)
ScrollView::OnScrollPresenterAnchorRequested
ScrollPresenter::RaiseAnchorRequested
ScrollPresenter::EnsureAnchorElementSelection
```
In the OpenClaw dump, anchor selection is requested through `FlowLayoutAlgorithm::Measure` / `ViewportManagerWithPlatformFeatures::SuggestedAnchor`. The explicitly forced-layout reproduction reached the same throw through `ScrollPresenter::ArrangeOverride`. The surrounding layout stack can therefore differ even though the failing native anchor-validation path is the same.
The two captured ARM64 dumps have matching WinUI PDB identities and share the first 13 native stowed-stack frames, including the throwing instruction at `Microsoft.UI.Xaml.Controls.dll + 0x325E48`.
`ItemsView::OnScrollViewAnchorRequested` checks that its retained target is non-null, but passes it to the setter without checking whether it is still a valid anchor. `ScrollPresenter::IsElementValidAnchor` requires a visible element that is the content itself or a descendant of the content. In this minimal reproduction, the visibility condition is deliberately invalidated.
The original OpenClaw invalidation may involve collapsing or recycling/detaching a row; the precise original transition is not asserted by this reduced reproduction. The reduced case isolates the confirmed native failure.
Crash occurs at https://github.com/microsoft/microsoft-ui-xaml/blob/6d4e2040ea8f5a2bd8130cf24d3e23985f8f8ba3/controls/dev/ScrollPresenter/ScrollingAnchorRequestedEventArgs.cpp#L43
which is called from https://github.com/microsoft/microsoft-ui-xaml/blob/e8442d07ae57d2d3e653e616831f504937881bd3/src/controls/dev/ItemsView/ItemsView.cpp#L972
Repro sample:
[WinUI.ItemsViewAnchorRepro.zip](https://github.com/user-attachments/files/32148084/WinUI.ItemsViewAnchorRepro.zip)
### Reactor-based reproduction
A minimal, unpackaged C# Reactor reproduction with complete source is now tracked in [microsoft/microsoft-ui-reactor#1213](https://github.com/microsoft/microsoft-ui-reactor/issues/1213). It also links back to [openclaw/openclaw-windows-node#1167](https://github.com/openclaw/openclaw-windows-node/issues/1167).
In that sample, the application does not explicitly collapse any container or call `UpdateLayout`. It starts a tail `StartBringItemIntoView` request and replaces the keyed history through Reactor state. A diagnostic run identified Reactor's `ElementFactory.RecycleElement -> TryParkForPool -> ParkOrphan` changing the retained target from `Visible` to `Collapsed` during recycling.
The minimal unpackaged sample crashed on its first button activation in two fresh ARM64 Debug launches. Its native dump reaches this issue's `ScrollingAnchorRequestedEventArgs::AnchorElement` failure through `FlowLayoutAlgorithm::Measure` / `ViewportManagerWithPlatformFeatures::SuggestedAnchor`, with the same PDB identities and 24 matching leading Controls-module frames as the original OpenClaw dump.
The button deliberately compresses the overlap between a pending tail request and history replacement. This demonstrates a Reactor-triggered instance of the WinUI failure without claiming that the whole OpenClaw scheduling path, the separate sustained hang, or an independent Reactor defect has been established. Details, versions, control-experiment results, and source are in the linked Reactor issue.
Contributor guide
Assessment
This issue has not been assessed yet.