Skip to content

Blazor SSR Task throws NavigationException from finalizer thread #62167

Open
@EffectivelyEfficient

Description

@EffectivelyEfficient

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When Blazor is used with SSR, and the OnInitializedAsync method throws an error such as the NavigationException, the task can end up on the finalizer thread.

It appears to require the OnInitializedAsync method to have made an async call first. However, even this is not reliable reproduction.

When I call NavigateTo() in OnInitializedAsync (server side) the browser is successfully redirected using navigationManager.NavigateTo(), but the NavigationException still hits the finalizer thread. In production it can take up to 22 minutes before the I saw it hit the "unobserved exception was rethrown by the finalizer thread" error.

Expected Behavior

NavigationException should be caught by the blazor code to trigger navigation.
It should not be rethrown by the finalizer thread.

Steps To Reproduce

  • Create an OnInitializedAsync method with 2s delay
  • Then call navigationManager.NavigateTo("/");
  • Call GC.Collect and WaitForPendingFinalizers to ensure prompt reproduction

Load the following example in the web browser. It should redirect to itself.
The second time it is called, the errors should be in the console.

Index.razor

@page "/"
@using BlazorApp1

<h1>Hello, world!</h1>

@code {
	[Inject]
	protected NavigationManager navigationManager { get; set; } = default!;

	protected override async Task OnInitializedAsync() {
		GC.Collect();
		GC.WaitForPendingFinalizers();
		GC.Collect();
		await Task.Delay(2000);
		navigationManager.NavigateTo("/");
	}
}

App.razor

@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using BlazorApp1

<Router AppAssembly="@typeof(App).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData"/>
    </Found>
</Router>

Program.cs:

using BlazorApp1;
using System.Runtime.InteropServices;

Console.WriteLine("Framework: " + RuntimeInformation.FrameworkDescription);
Console.WriteLine("Runtime Identifier: " + RuntimeInformation.RuntimeIdentifier);

AppDomain.CurrentDomain.UnhandledException += (sender, e) => {
		Console.WriteLine("Unhandled caught");
};

TaskScheduler.UnobservedTaskException += (sender, e) => {
	Console.WriteLine("Unhandled caught: " + e.Exception.ToString());
	e.SetObserved();
};

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents();
var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.UseAntiforgery();
app.MapRazorComponents<App>();
app.Run();

BlazorApp1.csproj:

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
	<ItemGroup>
	</ItemGroup>
</Project>

Exceptions (if any)

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:7275/ - - -
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/ (/)'
Unhandled caught: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. (Exception of type 'Microsoft.AspNetCore.Components.NavigationException' was thrown.)
 ---> Microsoft.AspNetCore.Components.NavigationException: Exception of type 'Microsoft.AspNetCore.Components.NavigationException' was thrown.
   at Microsoft.AspNetCore.Components.Endpoints.HttpNavigationManager.NavigateToCore(String uri, NavigationOptions options)
   at Microsoft.AspNetCore.Components.NavigationManager.NavigateToCore(String uri, Boolean forceLoad)
   at Microsoft.AspNetCore.Components.NavigationManager.NavigateTo(String uri, Boolean forceLoad, Boolean replace)
   at BlazorApp1.Pages.Index.OnInitializedAsync() in C:\Users\xxx\source\repos\bugcase\BlazorApp1\BlazorApp1\Pages\Index.razor:line 15
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
   at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.<WaitForNonStreamingPendingTasks>g__Execute|43_0()
   at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.WaitForResultReady(Boolean waitForQuiescence, PrerenderedComponentHtmlContent result)
   at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.RenderEndpointComponent(HttpContext httpContext, Type rootComponentType, ParameterView parameters, Boolean waitForQuiescence)
   --- End of inner exception stack trace ---
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/ (/)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/2 GET https://localhost:7275/ - 302 0 text/html;+charset=utf-8 2476.9080ms

.NET Version

9.0.300

Anything else?

dotnet --version
9.0.300

Microsoft Visual Studio Community 2022 (64-bit) - Version 17.14.3

dotnet --info
.NET SDK:
Version: 9.0.300
Commit: 15606fe0a8
Workload version: 9.0.300-manifests.af4147de
MSBuild version: 17.14.5+edd3bbf37

Runtime Environment:
OS Name: Windows
OS Version: 10.0.26100
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\9.0.300\

.NET workloads installed:
[aspire]
Installation Source: VS 17.14.36127.28
Manifest Version: 8.2.2/8.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.2.2\WorkloadManifest.json
Install Type: Msi

Configured to use loose manifests when installing new manifests.

Host:
Version: 9.0.5
Architecture: x64
Commit: e36e4d1a8f

.NET SDKs installed:
9.0.300 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
Not set

global.json file:
Not found

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download

Metadata

Metadata

Assignees

Labels

Needs: Attention 👋This issue needs the attention of a contributor, typically because the OP has provided an update.Needs: ReproIndicates that the team needs a repro project to continue the investigation on this issuearea-blazorIncludes: Blazor, Razor Componentsinvestigate

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions