[release/10.0] Fix null reference error in Virtualize component#66726
Merged
Conversation
When a Virtualize component is rapidly shown/hidden (e.g., in an autocomplete dropdown), the JS interop call to initialize the virtualize observers may arrive after the component has been removed from the DOM. This causes a 'Cannot read properties of null (reading parentElement)' error. This fix adds null checks at three points in Virtualize.ts: 1. Early return in init() if spacerBefore or spacerAfter are null 2. Check spacer.isConnected in mutation observer callback 3. Check spacerBefore.isConnected and spacerAfter.isConnected in intersection callback Fixes #65139
The existing null check handles the case where Blazor resolves element references to null. This adds an isConnected check for the theoretical scenario where references resolve to valid but disconnected elements, which would cause errors further in the init function (e.g., when Range.setStartAfter is called on disconnected nodes). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When init() returns early due to disconnected spacers, no observers are stored. The existing dispose() only called dotNetHelper.dispose() inside the 'if (observers)' block, leaking the DotNetObjectReference until the circuit closes. In rapid toggle scenarios this accumulates. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
pavelsavara
approved these changes
May 20, 2026
lewing
approved these changes
May 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Backport of #65207 to release/10.0
/cc @oroztocil @ilonatommy @javiercn
Fix null reference error in Virtualize component
Guard
Virtualize.tsinterop against spacers removed beforeinit()runs.Description
When a
Virtualizecomponent is rapidly shown/hidden (e.g. inside an autocomplete dropdown), the JS interopBlazor._internal.Virtualize.init()call can arrive after the component has been removed from the DOM. Blazor resolvesElementReferenceon the JS side viaquerySelector(...)at call time, so the spacer arguments can benull(or refer to elements that are no longer connected), causing:The fix adds defensive guards at three points in
Virtualize.ts:init()if either spacer isnullor notisConnected.MutationObservercallback bails out if the observed spacer is no longer connected.IntersectionObservercallback bails out if either spacer is no longer connected.It also moves
dotNetHelper.dispose()outside theif (observers)block indispose()so theDotNetObjectReferenceis always released, even wheninit()returned early and no observers were created.Fixes #65139
Customer Impact
Customer reported. Multiple reports of hitting this exception in a production scenario.
There is no usable workaround in user code: the error originates inside the framework's bundled JS interop, and
Virtualize<T>does not expose any hook to delay or skip init.Regression?
Pre-existing race condition in
VirtualizeJS interop, not a regression from a previous release.Risk
Only passive guards added to the TypeScript code for the Virtualize component. On the failure path the component silently no-ops instead of throwing. No public API change, no .NET-side change.
Verification
Verified on
mainvia PlaywrightrouteWebSocketinterception that selectively delays onlyVirtualize.initSignalR messages, reproducing the exact failure from the original report with 100% hit rate before the fix and 0 failures after. Automatic testing otherwise difficult. Existing BlazorVirtualizeE2E suites continue to pass. Full investigation report attached to the PR discussion (comment).Packaging changes reviewed?