Skip to content

Fix blank ErrorBoundary when multiple exceptions thrown in one batch - #69342

Open
dariatiurina wants to merge 3 commits into
dotnet:mainfrom
dariatiurina:dariatiurina-error-boundary-render-queue-fix
Open

dariatiurina wants to merge 3 commits into
dotnet:mainfrom
dariatiurina:dariatiurina-error-boundary-render-queue-fix

Conversation

@dariatiurina

@dariatiurina dariatiurina commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes ErrorBoundary rendering when multiple child components throw during the same render batch. The renderer now preserves the boundary's error content instead of leaving the boundary blank.

Changes

  • Tracks error boundaries with a pending forced subtree-clear render and queues that render only once per boundary.
  • Clears the tracking entry when the queued render runs or when the boundary is disposed before the render can run.
  • Allows the renderer test boundary helper to receive multiple exception notifications.

The first forced empty render remains ahead of the boundary's error-content render, so the failed subtree is discarded. Suppressing duplicate empty renders prevents a later one from clearing the error content.

Testing

  • Adds a unit regression test with three child components throwing during one render batch.
  • Adds an end-to-end test with multiple components throwing from a @foreach, verifying that the error UI is displayed without triggering the global error state.

Fixes #56950

@github-actions github-actions Bot added the area-blazor Includes: Blazor, Razor Components label Sep 16, 2026
@dariatiurina dariatiurina self-assigned this Sep 16, 2026
@dariatiurina
dariatiurina marked this pull request as ready for review September 16, 2026 13:41
@dariatiurina
dariatiurina requested a review from a team as a code owner September 16, 2026 13:41
Copilot AI lite review requested due to automatic review settings September 16, 2026 13:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Two moderate findings remain, along with a minor test-name nit.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Fixes blank ErrorBoundary output when multiple child components throw in one render batch.

Changes:

  • Coalesces pending subtree-clear renders per error boundary.
  • Adds unit and end-to-end regression coverage.
  • Updates test helpers for repeated exception notifications.
File summaries
File Summary Findings
src/Components/Components/src/RenderTree/Renderer.cs Tracks pending boundary subtree clears. Moderate (1 vote): Delayed exceptions after disposal can leave tracking IDs in the renderer.
src/Components/Components/test/ComponentBaseTest.cs Adds same-batch exception coverage. Moderate (2 votes): Assertions do not verify the boundary’s error content or render output.
src/Components/test/E2ETest/Tests/ErrorBoundaryTest.cs Adds end-to-end regression coverage. Nit (2 votes): Rename ForOnce to CanHandleMultipleExceptionsAtOnce.
src/Components/test/testassets/BasicTestApp/ErrorBoundaryTest/ForeachErrorsChild.razor Adds a throwing child component fixture. No findings.
src/Components/test/testassets/BasicTestApp/ErrorBoundaryTest/ErrorBoundaryCases.razor Adds the foreach error scenario. No findings.
src/Components/Components/test/RendererTest.cs Allows repeated exception notifications. No findings.
Review details

Suppressed comments (1)

src/Components/Components/src/RenderTree/Renderer.cs:1216

  • When a delayed exception is routed to a boundary after disposal, AddToRenderQueue returns because the state is no longer registered. Since this Add happens first, the disposal cleanup has already run and cannot remove the newly-added ID; each such boundary leaves an entry in the HashSet for the renderer lifetime. Guard the tracking add with a registered-state check (or make AddToRenderQueue report whether it enqueued).
                if (_errorBoundariesWithPendingSubtreeClear.Add(boundaryComponentId))
  • Files reviewed: 6/6 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +467 to +469
// Assert
Assert.NotNull(capturedBoundary);
Assert.NotNull(capturedBoundary.ReceivedException);
}

[Fact]
public void CanHandleMultipleExceptionsForOnce()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Includes: Blazor, Razor Components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Blazor ErrorBoundary error content not shown when exception occurs inside @foreach

2 participants