Describe the bug
- Avalonia version: 11.3.13
- OS: Windows 10.0.19045 (also reported under Wine / Steam Deck —
Z:\home\deck\...)
- Runtime: .NET 10.0.5, NativeAOT (
RuntimeFeature.IsDynamicCodeSupported == false)
- Renderer: default compositing renderer (Win32 backend)
Summary
An unobserved NullReferenceException is raised from inside the renderer's hit-test path when the pointer-over preprocessor reacts to a SceneInvalidated event. The exception is swallowed by the dispatcher (it surfaces only via TaskScheduler.UnobservedTaskException), so the app does not crash, but it is logged as an unhandled fault by crash-reporting SDKs (Sentry in our case).
Stack trace
System.NullReferenceException: Object reference not set to an instance of an object.
at Avalonia.Rendering.Composition.CompositionTarget.HitTestCore(CompositionVisual, Point, PooledList`1, Func`2)
at Avalonia.Rendering.Composition.CompositionTarget.HitTestCore(...) [~50x recursion through visual tree]
at Avalonia.Rendering.Composition.CompositionTarget.TryHitTest(Point, CompositionVisual, Func`2)
at Avalonia.Rendering.Composition.CompositingRenderer.<HitTest>d__25.MoveNext()
at System.Linq.Enumerable.TryGetFirstNonIterator[TSource](IEnumerable`1, out bool)
at Avalonia.VisualTree.VisualExtensions.GetVisualAt(Visual, Point, Func`2)
at Avalonia.Input.InputExtensions.InputHitTest(IInputElement, Point, bool)
at Avalonia.Input.PointerOverPreProcessor.SceneInvalidated(Rect)
at Avalonia.Controls.TopLevel.SceneInvalidated(object sender, SceneInvalidatedEventArgs e)
at Avalonia.Threading.DispatcherOperation.InvokeCore()
Wrapped as: AggregateException → NullReferenceException via UnobservedTaskException (HResult 0x80004003 inside, 0x80131500 outer).
Analysis
The NRE happens during the recursive HitTestCore walk after the renderer has dispatched a SceneInvalidated callback to the UI thread. By the time the dispatcher op runs, some CompositionVisual/child reference in the tree appears to be null - consistent with hit-testing a scene that is concurrently being torn down (a TopLevel closing, a control being unloaded, or a visual subtree being detached) while the pointer-over preprocessor is replaying the last known cursor position.
The dispatcher op is fire-and-forget, so the exception is observed only when the resulting Task is finalized - it does not crash the app, but it is a real bug in framework code (no user code is on the stack).
Suggested fix direction
PointerOverPreProcessor.SceneInvalidated (and/or CompositionTarget.HitTestCore) should be defensive against a partially-detached/disposed visual subtree - either skip the hit test when the target TopLevel / root composition visual is no longer attached, or null-guard the child traversal in HitTestCore.
Notes
- Crash reports reach us via Sentry's
UnobservedTaskException integration; the user does not see a crash.
- One reporter is on Wine/Proton (Steam Deck) where event timing differs from native Win32 and may widen the race window. Mentioning in case it helps reproduce.
- Project is published with NativeAOT, but the stack is entirely managed and I don't believe AOT is causally relevant.
To Reproduce
I do not have a tight standalone repro yet. In our app the trace is most consistent with: a window/TopLevel closing or a major visual-tree swap occurring while the cursor is over the affected window. It is intermittent and we have only seen it in the wild (production crash reports), not locally.
Expected behavior
No response
Avalonia version
11.3.13
OS
Linux
Additional context
No response
Describe the bug
Z:\home\deck\...)RuntimeFeature.IsDynamicCodeSupported == false)Summary
An unobserved
NullReferenceExceptionis raised from inside the renderer's hit-test path when the pointer-over preprocessor reacts to aSceneInvalidatedevent. The exception is swallowed by the dispatcher (it surfaces only viaTaskScheduler.UnobservedTaskException), so the app does not crash, but it is logged as an unhandled fault by crash-reporting SDKs (Sentry in our case).Stack trace
Wrapped as:
AggregateException→NullReferenceExceptionviaUnobservedTaskException(HResult0x80004003inside,0x80131500outer).Analysis
The NRE happens during the recursive
HitTestCorewalk after the renderer has dispatched aSceneInvalidatedcallback to the UI thread. By the time the dispatcher op runs, someCompositionVisual/child reference in the tree appears to be null - consistent with hit-testing a scene that is concurrently being torn down (aTopLevelclosing, a control being unloaded, or a visual subtree being detached) while the pointer-over preprocessor is replaying the last known cursor position.The dispatcher op is fire-and-forget, so the exception is observed only when the resulting
Taskis finalized - it does not crash the app, but it is a real bug in framework code (no user code is on the stack).Suggested fix direction
PointerOverPreProcessor.SceneInvalidated(and/orCompositionTarget.HitTestCore) should be defensive against a partially-detached/disposed visual subtree - either skip the hit test when the targetTopLevel/ root composition visual is no longer attached, or null-guard the child traversal inHitTestCore.Notes
UnobservedTaskExceptionintegration; the user does not see a crash.To Reproduce
I do not have a tight standalone repro yet. In our app the trace is most consistent with: a window/
TopLevelclosing or a major visual-tree swap occurring while the cursor is over the affected window. It is intermittent and we have only seen it in the wild (production crash reports), not locally.Expected behavior
No response
Avalonia version
11.3.13
OS
Linux
Additional context
No response