dotnet/aspnetcore · error · InvalidOperationException
Render mode already set.
Error message
Render mode already set.
What it means
ComponentStatePersistenceManager.SetPlatformRenderMode sets the render mode used for platform-persisted service state through PersistentServicesRegistry. The registry's RenderMode can be assigned exactly once; calling SetPlatformRenderMode again after a non-null render mode is already stored throws. This prevents conflicting platform render-mode declarations when multiple render hosts (e.g., Server and WebAssembly) attempt to claim the same registry.
Solutions
- Call SetPlatformRenderMode at most once per manager; delegate platform render-mode selection to a single owning layer.
- If the mode is already set, skip the call; guard with a check of whether the registry already has a RenderMode if you have internal access.
- Reconcile conflicting render-mode configuration so only one platform render mode applies per services registry.
Example fix
// before: setting platform render mode twice manager.SetPlatformRenderMode(RenderMode.InteractiveServer); manager.SetPlatformRenderMode(RenderMode.InteractiveWebAssembly); // throws // after: set once; ensure only the platform host assigns it manager.SetPlatformRenderMode(RenderMode.InteractiveServer); // do not call again; configure other endpoints to reuse the same manager
Defensive patterns
Strategy: validation
Validate before calling
// Only one platform host should set the render mode.
if (platformRenderMode == null) return;
try
{
manager.SetPlatformRenderMode(platformRenderMode);
}
catch (InvalidOperationException) { /* already set; ensure consistency */ } Try / catch
try { manager.SetPlatformRenderMode(renderMode); }
catch (InvalidOperationException ex) when (ex.Message == "Render mode already set.")
{
// Log and verify the already-set mode matches expectation; otherwise reconcile config.
} Prevention
- Assign the platform render mode from a single owning host layer.
- Do not call SetPlatformRenderMode per-request; do it once at startup.
- Ensure Blazor Web App render-mode configuration is consistent across endpoints.
When it happens
Trigger: Invoking SetPlatformRenderMode twice with different IComponentRenderMode values on the same manager. A hosting layer that registers the platform render mode during prerender and a second layer registers it again during interactive startup. Two endpoints with different configured render modes sharing the same services registration.
Common situations: Misconfigured Blazor Web App where both a prerendering endpoint and an interactive circuit attempt to set the platform render mode. Custom hosts that call SetPlatformRenderMode in startup and again per-request. Mixing InteractiveServer and InteractiveWebAssembly platform configuration on the same app instance.
Related errors
- ' ' is flagged with SingleDelivery, but the selected…
- A public property ' ' on component type ' ' with a public…
- Cannot merge mismatching component descriptors
- Cannot supply a component of type
- Cannot update existing state: previous state has not been…
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/ff2795cb74c239ab.
Report an issue: GitHub.
Appendix: source
Thrown at src/Components/Components/src/PersistentState/ComponentStatePersistenceManager.cs:167
await store.PersistStateAsync(_currentState);
return true;
}
}
/// <summary>
/// Initializes the render mode for state persisted by the platform.
/// </summary>
/// <param name="renderMode">The render mode to use for state persisted by the platform.</param>
/// <exception cref="InvalidOperationException">when the render mode is already set.</exception>
public void SetPlatformRenderMode(IComponentRenderMode renderMode)
{
if (_servicesRegistry == null)
{
return;
}
else if (_servicesRegistry?.RenderMode != null)
{
throw new InvalidOperationException("Render mode already set.");
}
_servicesRegistry!.RenderMode = renderMode;
}
private void InferRenderModes(Renderer renderer)
{
// We are iterating backwards to allow the callbacks to remove themselves from the list.
// Otherwise, we would have to make a copy of the list to avoid running into situations
// where we don't run all the callbacks because the count of the list changed while we
// were iterating over it.
// It is not allowed to register a callback while we are persisting the state, so we don't
// need to worry about new callbacks being added to the list.
for (var i = _registeredCallbacks.Count - 1; i >= 0; i--)
{
var registration = _registeredCallbacks[i];
if (registration.RenderMode != null)
{View on GitHub (pinned to 3600ca084e)