This content was largely generated by AI. AI makes mistakes.
Reactor ItemsView history replacement exposes WinUI's invalid bring-into-view anchor crash
Summary
Replacing a keyed Reactor ItemsView history while an
ItemsView.StartBringItemIntoView request is pending can terminate the process
with E_INVALIDARG (0x80070057, surfaced as 0xC000027B).
This is a Reactor-based reproduction of the native WinUI bug tracked in
microsoft/microsoft-ui-xaml#11865.
Unlike the native minimal reproduction, the application never collapses a
container. A diagnostic run showed Reactor doing that during recycling:
ElementFactory<T>.RecycleElement -> TryParkForPool -> ParkOrphan.
The purpose of this report is to document the confirmed Reactor/WinUI interaction
and request investigation of a safe integration behavior/regression test. It does
not establish that Reactor, rather than WinUI, must own the eventual fix.
Related application investigation:
openclaw/openclaw-windows-node#1167.
OpenClaw's application-side workaround is
openclaw/openclaw-windows-node#1407 (fix(chat): work around WinUI session-switch crash).
That workaround avoids index-based bring navigation. It is not included in this
sample.
Reproduction
The complete sample is included below: one Program.cs and a small project
file. It starts with ReactorApp.Run<ChatRepro>() and is
unpackaged, with no application XAML, custom titlebar, window sizing, icons,
assets, or packaging setup.
-
Save the two files below in an empty directory. On Windows ARM64, build and
launch the project:
winapp run .\ReactorItemsViewRepro.csproj --arch arm64 -p Platform=ARM64 --debug-output
-
Wait for the synthetic session history and Switch session button to appear.
-
Click Switch session once.
Actual: the process crashes during subsequent native layout with a stowed
E_INVALIDARG. In the confirmed runs, the native bring call returned and the
button handler requested the new Reactor state before the crash.
Expected: the old pending navigation should be canceled, superseded, or
otherwise handled safely when its row is recycled. Replacing the history should
not terminate the process.
The first button activation reproduced the crash in two out of two fresh,
uninstrumented launches of the minimal unpackaged sample, using UI Automation
Invoke. The earlier packaged prototype also crashed on its first click in three
out of three launches, including a physical-pointer click. These are observed
success rates, not guarantees across machines.
What the sample models
- One Reactor root and one persistent keyed
ItemsView.
- Two immutable synthetic histories with 77 variable-height text rows each.
- Stable, unique keys within each history; different keys between sessions.
ItemContainer row roots with .WithKey(row.Key).
StackLayout, no selection, and no item invocation.
- Non-animated, bottom-aligned
ItemsView.StartBringItemIntoView.
- A
UseState session change, causing Reactor to reconcile the history.
These are the relevant list shapes used by OpenClaw before its workaround.
OpenClaw embeds its root in ReactorHostControl; the simplified sample uses
ReactorApp.Run instead. The embedded host and packaging are not necessary to
trigger the bug.
Timing reduction: the button deliberately starts a bring request for the
current history's tail, then immediately calls the state setter for the other
history. This makes the pending-navigation/history-replacement overlap reliable.
OpenClaw reaches overlapping operations through asynchronous history updates and
queued tail requests; this sample does not reproduce its entire scheduling
pipeline.
There is no explicit UpdateLayout, application-written visibility change,
custom element factory, manual ItemsSource mutation, reflection, artificial
exception, timer, network, Markdown renderer, or OpenClaw dependency. The requested
index is 76 and the current history contains 77 items when the native call starts.
Program.cs
using Microsoft.UI.Reactor;
using Microsoft.UI.Reactor.Core;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using static Microsoft.UI.Reactor.Factories;
using NativeItemsView = Microsoft.UI.Xaml.Controls.ItemsView;
ReactorApp.Run<ChatRepro>();
public sealed class ChatRepro : Component
{
private sealed record Message(string Key, string Text);
private static readonly Message[][] Histories = Enumerable.Range(0, 2)
.Select(session => Enumerable.Range(0, 77).Select(index => new Message(
$"session:{session}|message:{index}",
$"Session {session + 1}, message {index + 1}\n"
+ string.Concat(Enumerable.Repeat(
"Synthetic chat text. This row has a different measured height.\n",
index % 7 + 1)))).ToArray()).ToArray();
private NativeItemsView? _itemsView;
public override Element Render()
{
var (session, setSession) = UseState(0);
var rows = Histories[session];
var items = ItemsView(
rows,
static row => row.Key,
(row, _) => ItemContainer(
TextBlock(row.Text).TextWrapping(TextWrapping.Wrap))
.WithKey(row.Key)) with
{
LayoutKind = ItemsViewLayoutKind.StackLayout,
SelectionMode = ItemsViewSelectionMode.None,
IsItemInvokedEnabled = false,
};
return Grid(
[GridSize.Star()],
[GridSize.Auto, GridSize.Star()],
Button("Switch session", () =>
{
if (_itemsView is not { IsLoaded: true } view)
throw new InvalidOperationException("The timeline is not loaded.");
// Put the old history's tail request in flight, then replace the
// keyed history through Reactor. No visibility or layout mutation.
view.StartBringItemIntoView(rows.Length - 1, new BringIntoViewOptions
{
AnimationDesired = false,
VerticalAlignmentRatio = 1.0,
});
setSession(1 - session);
}).Grid(row: 0),
items.Set(view => _itemsView = view)
.Grid(row: 1));
}
}
ReactorItemsViewRepro.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
<Platforms>x64;ARM64</Platforms>
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == ''">win-$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant())</RuntimeIdentifier>
<UseWinUI>true</UseWinUI>
<WindowsPackageType>None</WindowsPackageType>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.UI.Reactor" Version="0.1.0-preview.15" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="2.4.0" />
</ItemGroup>
</Project>
Observed Reactor transition
In a diagnostic build of the earlier packaged prototype, a read-only
visibility-property observer was registered on the current tail container after
StartBringItemIntoView returned. It reported:
REPRO: bring session=1, index=76
REPRO: target before reconcile: Visible
REPRO: requested session=2
REPRO: target visibility changed to Collapsed
The captured managed stack identified this path, shown in caller-to-callee order:
ReactorHostControl.Render
Reconciler.BindItemsViewErasedKeyedItems
Reconciler.ApplyItemsViewErasedKeyedDiffOrFallback
KeyedListDiff.Apply / ApplyCore / ApplyGeneral
KeyedListDiff.Bailout
ReactorListState.Reset
ObservableCollection.OnCollectionChanged
[WinUI recycling]
ElementFactory<T>.RecycleElement
TryParkForPool
ParkOrphan
UIElement.Visibility = Collapsed
The disjoint session keys take the keyed-diff reset path in this reproduction.
The observer neither changed visibility nor caught the failure. It was removed
before the confirmation runs; it is not required or present in the delivered
unpackaged sample.
Relevant Reactor source, pinned to the tested package's repository commit:
The factory comments explain that parking collapsed containers prevents ghost
rows while WinUI keeps recycled elements parented. Simply deleting that collapse
is therefore not proposed as a safe fix.
Native failure and comparison with OpenClaw
The minimal unpackaged sample dump contains 0x80070057 in its stowed
exceptions. Matching Microsoft symbol-server PDBs resolve the original throw to:
ScrollingAnchorRequestedEventArgs::AnchorElement
ScrollingAnchorRequestedEventArgs.cpp:43
Microsoft.UI.Xaml.Controls.dll + 0x325E48
ItemsView::OnScrollViewAnchorRequested
ItemsView.cpp:972
Microsoft.UI.Xaml.Controls.dll + 0x360B04
ScrollPresenter::EnsureAnchorElementSelection
ScrollPresenterAnchoring.cpp:367
Microsoft.UI.Xaml.Controls.dll + 0x3287E0
The minimal unpackaged run also includes:
FlowLayoutAlgorithm::Measure
-> ViewportManagerWithPlatformFeatures::SuggestedAnchor
-> ScrollPresenter::AnchorElement
-> EnsureAnchorElementSelection
-> ItemsView::OnScrollViewAnchorRequested
-> ScrollingAnchorRequestedEventArgs::AnchorElement
The first 24 Controls-module frames in the minimal unpackaged dump, compared by module-relative address,
match the original OpenClaw crash's original-throw context. The module PDB
identities also match:
| PDB |
GUID plus age |
Microsoft.ui.xaml.pdb |
1AA39E9A93038419472E12ABB014892F1 |
Microsoft.UI.Xaml.Controls.pdb |
EF5A6F388B15033C45BBC2D6F489BE2B1 |
An earlier prototype run entered anchor selection through
ScrollPresenter::ArrangeOverride instead. Both reach the same anchor setter;
the minimal unpackaged run matches OpenClaw's measure-path entry. This is not
just a match on the generic top-level 0xC000027B crash code.
Control experiment and validation
| Experiment |
Result |
| Clean/build minimal unpackaged ARM64 Debug sample |
Passed, 0 warnings, 0 errors |
| Minimal unpackaged sample, two fresh launches |
First button activation crashed in both; native dump confirmed the anchor setter and OpenClaw measure path |
| Earlier packaged prototype, three fresh launches |
First click crashed in all three |
| Temporary visibility observer in the earlier prototype |
Reactor collapsed the pending tail target, then the process crashed |
| Earlier prototype with only the native bring request omitted from the button's behavior |
20 session switches completed; all 20 selected-session transitions verified through UI Automation; process remained responsive |
The earlier prototype's no-bring experiment is evidence that keyed replacement alone was insufficient
to trigger this failure in that run. It is not a general stress-safety claim for
Reactor. There is no no-bring mode or workaround UI in the delivered sample.
The project, screenshots, diagnostic logs, and dumps were generated locally with
synthetic data. No private chat data was used. Full dumps are not needed to run
the reproduction.
Environment
Tested September 14, 2026:
| Component |
Version |
| OS |
Windows 11, build 10.0.26200, ARM64 |
| Configuration |
Unpackaged Reactor application, ARM64 Debug |
| .NET SDK |
10.0.400 |
| Target framework |
net10.0-windows10.0.26100.0 |
Microsoft.UI.Reactor |
0.1.0-preview.15 |
| Reactor package source commit |
f17ce2dd12083e7e8709883c7c4ccd04c556810d |
Microsoft.WindowsAppSDK |
2.4.0 |
| Native Xaml and Controls file version |
3.2.3.2608 |
| Native source revision |
aa188bfdf74608810e8e57228db6dd137f4e74e4 |
| WinApp CLI used for launch/input/crash capture |
0.6.3-prerelease.36 |
The NuGet versions are intentionally pinned to match the investigated OpenClaw
build, not selected as recommendations for new applications. The inspected
Reactor checkout was at d9ee0d9b; its relevant factory and ItemsView binding
files were unchanged from the package commit above.
Final Program.cs SHA-256:
D8ED327C3704B56153D9791C932DD5F60D4BF3290BB8EB538D20AD95F88F31F7.
Scope and requested investigation
This confirms that normal Reactor recycling can expose the already-reported
WinUI invalid-anchor failure without an application explicitly hiding a row.
It does not prove an independent Reactor defect, test a newer source-built
Reactor version, establish behavior on x64/Release, or resolve the separate
sustained-hang report in OpenClaw.
Please investigate how pending index-based bring requests should interact with
Reactor's keyed history replacement and collapsed-container recycling, and add a
real-WinUI regression test for this combination. Coordinate the ownership of the
fix with microsoft/microsoft-ui-xaml#11865 rather than assuming that suppressing a
synchronous managed exception or leaving parked containers visible is sufficient.
This content was largely generated by AI. AI makes mistakes.
Reactor ItemsView history replacement exposes WinUI's invalid bring-into-view anchor crash
Summary
Replacing a keyed Reactor
ItemsViewhistory while anItemsView.StartBringItemIntoViewrequest is pending can terminate the processwith
E_INVALIDARG(0x80070057, surfaced as0xC000027B).This is a Reactor-based reproduction of the native WinUI bug tracked in
microsoft/microsoft-ui-xaml#11865.
Unlike the native minimal reproduction, the application never collapses a
container. A diagnostic run showed Reactor doing that during recycling:
ElementFactory<T>.RecycleElement -> TryParkForPool -> ParkOrphan.The purpose of this report is to document the confirmed Reactor/WinUI interaction
and request investigation of a safe integration behavior/regression test. It does
not establish that Reactor, rather than WinUI, must own the eventual fix.
Related application investigation:
openclaw/openclaw-windows-node#1167.
OpenClaw's application-side workaround is
openclaw/openclaw-windows-node#1407 (fix(chat): work around WinUI session-switch crash).
That workaround avoids index-based bring navigation. It is not included in this
sample.
Reproduction
The complete sample is included below: one
Program.csand a small projectfile. It starts with
ReactorApp.Run<ChatRepro>()and isunpackaged, with no application XAML, custom titlebar, window sizing, icons,
assets, or packaging setup.
Save the two files below in an empty directory. On Windows ARM64, build and
launch the project:
Wait for the synthetic session history and Switch session button to appear.
Click Switch session once.
Actual: the process crashes during subsequent native layout with a stowed
E_INVALIDARG. In the confirmed runs, the native bring call returned and thebutton handler requested the new Reactor state before the crash.
Expected: the old pending navigation should be canceled, superseded, or
otherwise handled safely when its row is recycled. Replacing the history should
not terminate the process.
The first button activation reproduced the crash in two out of two fresh,
uninstrumented launches of the minimal unpackaged sample, using UI Automation
Invoke. The earlier packaged prototype also crashed on its first click in three
out of three launches, including a physical-pointer click. These are observed
success rates, not guarantees across machines.
What the sample models
ItemsView.ItemContainerrow roots with.WithKey(row.Key).StackLayout, no selection, and no item invocation.ItemsView.StartBringItemIntoView.UseStatesession change, causing Reactor to reconcile the history.These are the relevant list shapes used by OpenClaw before its workaround.
OpenClaw embeds its root in
ReactorHostControl; the simplified sample usesReactorApp.Runinstead. The embedded host and packaging are not necessary totrigger the bug.
Timing reduction: the button deliberately starts a bring request for the
current history's tail, then immediately calls the state setter for the other
history. This makes the pending-navigation/history-replacement overlap reliable.
OpenClaw reaches overlapping operations through asynchronous history updates and
queued tail requests; this sample does not reproduce its entire scheduling
pipeline.
There is no explicit
UpdateLayout, application-written visibility change,custom element factory, manual
ItemsSourcemutation, reflection, artificialexception, timer, network, Markdown renderer, or OpenClaw dependency. The requested
index is 76 and the current history contains 77 items when the native call starts.
Program.cs
ReactorItemsViewRepro.csproj
Observed Reactor transition
In a diagnostic build of the earlier packaged prototype, a read-only
visibility-property observer was registered on the current tail container after
StartBringItemIntoViewreturned. It reported:The captured managed stack identified this path, shown in caller-to-callee order:
The disjoint session keys take the keyed-diff reset path in this reproduction.
The observer neither changed visibility nor caught the failure. It was removed
before the confirmation runs; it is not required or present in the delivered
unpackaged sample.
Relevant Reactor source, pinned to the tested package's repository commit:
The factory comments explain that parking collapsed containers prevents ghost
rows while WinUI keeps recycled elements parented. Simply deleting that collapse
is therefore not proposed as a safe fix.
Native failure and comparison with OpenClaw
The minimal unpackaged sample dump contains
0x80070057in its stowedexceptions. Matching Microsoft symbol-server PDBs resolve the original throw to:
The minimal unpackaged run also includes:
The first 24 Controls-module frames in the minimal unpackaged dump, compared by module-relative address,
match the original OpenClaw crash's original-throw context. The module PDB
identities also match:
Microsoft.ui.xaml.pdb1AA39E9A93038419472E12ABB014892F1Microsoft.UI.Xaml.Controls.pdbEF5A6F388B15033C45BBC2D6F489BE2B1An earlier prototype run entered anchor selection through
ScrollPresenter::ArrangeOverrideinstead. Both reach the same anchor setter;the minimal unpackaged run matches OpenClaw's measure-path entry. This is not
just a match on the generic top-level
0xC000027Bcrash code.Control experiment and validation
The earlier prototype's no-bring experiment is evidence that keyed replacement alone was insufficient
to trigger this failure in that run. It is not a general stress-safety claim for
Reactor. There is no no-bring mode or workaround UI in the delivered sample.
The project, screenshots, diagnostic logs, and dumps were generated locally with
synthetic data. No private chat data was used. Full dumps are not needed to run
the reproduction.
Environment
Tested September 14, 2026:
10.0.26200, ARM6410.0.400net10.0-windows10.0.26100.0Microsoft.UI.Reactor0.1.0-preview.15f17ce2dd12083e7e8709883c7c4ccd04c556810dMicrosoft.WindowsAppSDK2.4.03.2.3.2608aa188bfdf74608810e8e57228db6dd137f4e74e40.6.3-prerelease.36The NuGet versions are intentionally pinned to match the investigated OpenClaw
build, not selected as recommendations for new applications. The inspected
Reactor checkout was at
d9ee0d9b; its relevant factory and ItemsView bindingfiles were unchanged from the package commit above.
Final
Program.csSHA-256:D8ED327C3704B56153D9791C932DD5F60D4BF3290BB8EB538D20AD95F88F31F7.Scope and requested investigation
This confirms that normal Reactor recycling can expose the already-reported
WinUI invalid-anchor failure without an application explicitly hiding a row.
It does not prove an independent Reactor defect, test a newer source-built
Reactor version, establish behavior on x64/Release, or resolve the separate
sustained-hang report in OpenClaw.
Please investigate how pending index-based bring requests should interact with
Reactor's keyed history replacement and collapsed-container recycling, and add a
real-WinUI regression test for this combination. Coordinate the ownership of the
fix with microsoft/microsoft-ui-xaml#11865 rather than assuming that suppressing a
synchronous managed exception or leaving parked containers visible is sufficient.