Skip to content

[Blazor] Hard Navigation during Circuit Setup causes Circuit drop and fails to start a new circuit #63622

@joeswyoung

Description

@joeswyoung

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When a hard navigation occurs before OnConnectionUpAsync has completed the browser gets an error saying "Error: Circuit has been shut down due to error". No message is displayed to the user that they should try to reconnect/refresh.

The exception I see on the server is "System.InvalidOperationException: No root component exists with SSR component ID 1" and from the logs I can see the RenderTree has already started disposing the components when "Update root components" is called by the CircuitHost so it's not surprising that there is an exception.

I came across this bug because in our app we make some async calls during OnCircuitOpenedAsync and OnConnectionUpAsync which makes the process take longer, which would expand the window when this could happen. I can handle this error with a CreateInboundActivityHandler but I don't want to interfere with the frameworks circuit management if this is expected behavior. Otherwise is the guidance from the Blazor team to keep those CircuitHandler methods as light weight as possible to avoid this issue? Please correct me if my understanding of this issue is incorrect.

Expected Behavior

The circuit to be disposed of cleanly on a hard nav and have the circuit state communicated to the circuit host so it does not try to perform an Invalid Operation. Then either continue on the old circuit or start a new circuit.

If this is not possible any guidance on how to mitigate this issue would be appreciated.

Steps To Reproduce

Add this CircuitHandler to the Blazor Template and set the home page of the demo to InteractiveServerRenderMode.

` public class NavIssueTestCircuitHandler : CircuitHandler
{
public override async Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
{
await base.OnCircuitOpenedAsync(circuit, cancellationToken);
}

    public override async Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
    {
        // To make the window larger 
        await Task.Delay(TimeSpan.FromSeconds(1.5), cancellationToken);
    }
}

`

Then once the project is started, reload the page and quickly navigate to the counter using the nav menu (increase the timing window if needed). The circuit will be down and the counter will not work.

Exceptions (if any)

Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Debug: Update root components started.
Exception thrown: 'System.InvalidOperationException' in Microsoft.AspNetCore.Components.Server.dll
Exception thrown: 'System.InvalidOperationException' in System.Private.CoreLib.dll
'NavIssueDemo.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\9.0.8\System.Diagnostics.StackTrace.dll'. Symbol loading disabled by Include/Exclude setting.
'NavIssueDemo.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\9.0.8\System.Reflection.Metadata.dll'. Symbol loading disabled by Include/Exclude setting.
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Debug: Update root components failed.

System.InvalidOperationException: No root component exists with SSR component ID 1.
at Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer.WebRootComponentManager.GetRequiredWebRootComponent(Int32 ssrComponentId)
at Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.<>c__DisplayClass67_0.b__0()
at Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.PerformRootComponentOperations(RootComponentOperation[] operations, Boolean shouldWaitForQuiescence)
at Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.<>c__DisplayClass65_0.<b__0>d.MoveNext()
Microsoft.AspNetCore.Components.Server.Circuits.CircuitRegistry: Debug: Circuit with id rCgXQwC-HiE-tBuBdKKVs-QnyZuaX3dqQQlVmFqoM1Q has been removed from the registry for permanent disconnection.
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Debug: Disposing circuit 'rCgXQwC-HiE-tBuBdKKVs-QnyZuaX3dqQQlVmFqoM1Q' started.
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Debug: Circuit id 'rCgXQwC-HiE-tBuBdKKVs-QnyZuaX3dqQQlVmFqoM1Q' disconnected from connection 'j4WVMc8W18cOwbmO6ELlAg'.
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Debug: Closing circuit with id 'rCgXQwC-HiE-tBuBdKKVs-QnyZuaX3dqQQlVmFqoM1Q'.
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Debug: Disposing circuit 'rCgXQwC-HiE-tBuBdKKVs-QnyZuaX3dqQQlVmFqoM1Q' succeeded.
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Debug: An exception occurred on the circuit host 'rCgXQwC-HiE-tBuBdKKVs-QnyZuaX3dqQQlVmFqoM1Q' while the client is disconnected.

.NET Version

9.0.304

Anything else?

Blazor Nav Issue Logs.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-blazorIncludes: Blazor, Razor Components

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions