dotnet/aspnetcore · error · InvalidOperationException

The render handle is not yet assigned.

Error message

The render handle is not yet assigned.

What it means

RenderHandle.ThrowNotInitialized is a [DoesNotReturn] helper called by the Dispatcher property getter and the Render method when _renderer is null. It throws InvalidOperationException with the message 'The render handle is not yet assigned.' This is the most commonly hit variant because Dispatcher is used extensively (e.g., invoking back to the sync context) and Render is called by ComponentBase.StateHasChanged().

Source

Thrown at src/Components/Components/src/RenderHandle.cs:123

        _renderer.AddToRenderQueue(_componentId, renderFragment);
    }

    /// <summary>
    /// Dispatches an <see cref="Exception"/> to the <see cref="Renderer"/>.
    /// </summary>
    /// <param name="exception">The <see cref="Exception"/> that will be dispatched to the renderer.</param>
    /// <returns>A <see cref="Task"/> that will be completed when the exception has finished dispatching.</returns>
    public Task DispatchExceptionAsync(Exception exception)
    {
        var renderer = _renderer;
        var componentId = _componentId;
        return Dispatcher.InvokeAsync(() => renderer!.HandleComponentException(exception, componentId));
    }

    [DoesNotReturn]
    private static void ThrowNotInitialized()
    {
        throw new InvalidOperationException("The render handle is not yet assigned.");
    }
}

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Use TestRenderer or bUnit's TestContext to properly attach the render handle before calling StateHasChanged or accessing Dispatcher.
  2. Ensure StateHasChanged / Render is only called after the component is initialized (OnInitialized or later), never in the constructor.
  3. Guard with RenderHandle.IsInitialized before calling StateHasChanged in code paths that may run pre-initialization.
  4. Ensure the component is rendered through the normal rendering pipeline rather than invoked manually.

Example fix

// before (test)
var component = new MyComponent();
component.StateHasChanged(); // calls Render on uninitialized handle -> throws

// after (bUnit)
using var ctx = new TestContext();
var cut = ctx.RenderComponent<MyComponent>();
// StateHasChanged works inside component lifecycle
Defensive patterns

Strategy: type-guard

Validate before calling

if (renderHandle.IsInitialized)
{
    renderHandle.Render(builder => { /* ... */ });
}
// Or guard StateHasChanged-equivalent logic
if (renderHandle.IsInitialized)
{
    await renderHandle.Dispatcher.InvokeAsync(() => { /* ... */ });
}

Type guard

static bool CanRender(RenderHandle handle) => handle.IsInitialized;

// In ComponentBase overrides, guard StateHasChanged calls:
protected void SafeStateHasChanged()
{
    if (renderHandle.IsInitialized) StateHasChanged();
}

Prevention

When it happens

Trigger: Calling StateHasChanged() or accessing RenderHandle.Dispatcher on a component whose RenderHandle has not been assigned. This happens in tests that call lifecycle methods directly without a renderer, or when a component calls StateHasChanged during construction (before the handle is set). It can also occur if code captures a RenderHandle from a disposed or never-initialized component and later calls Render on it.

Common situations: Unit tests invoking SetParametersAsync or StateHasChanged on a manually-constructed component; calling StateHasChanged inside a constructor; components used outside the Blazor pipeline (e.g., in a plain C# service); incorrect bUnit setup.

Related errors


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/6d5d4f6a75cff07c. Report an issue: GitHub.