dotnet/aspnetcore · error

Unexpected renderer ID '${rendererId}' encountered while dis

Error message

Unexpected renderer ID '${rendererId}' encountered while discovering new state.

What it means

Thrown in refreshRootComponents() at WebRootComponentManager.ts:324 while iterating rendererIds collected from persisted-state discovery. The loop only knows how to discover state for WebRendererId.Server and WebRendererId.WebAssembly; any other numeric rendererId means the enum gained a value the JS client does not understand, so it refuses rather than silently dropping persisted state for unknown renderers.

Source

Thrown at src/Components/Web.JS/src/Services/WebRootComponentManager.ts:324

          // and if there are no updates on this batch, push an empty set of operations
          // to ensure we send the state over. Same for wasm below.
          serverState = discoverServerPersistedState(document) || '';
          if (serverState && serverState !== '') {
            const ops = operationsByRendererId.get(WebRendererId.Server);
            if (!ops) {
              operationsByRendererId.set(WebRendererId.Server, []);
            }
          }
        } else if (rendererId === WebRendererId.WebAssembly) {
          webAssemblyState = discoverWebAssemblyPersistedState(document) || '';
          if (webAssemblyState && webAssemblyState !== '') {
            const ops = operationsByRendererId.get(WebRendererId.WebAssembly);
            if (!ops) {
              operationsByRendererId.set(WebRendererId.WebAssembly, []);
            }
          }
        } else {
          throw new Error(`Unexpected renderer ID '${rendererId}' encountered while discovering new state.`);
        }
      }
    }

    for (const [rendererId, operations] of operationsByRendererId) {
      const batch: RootComponentOperationBatch = {
        batchId: this._nextOperationBatchId++,
        operations,
      };
      this._pendingOperationBatches[batch.batchId] = batch;
      const batchJson = JSON.stringify(batch);

      if (rendererId === WebRendererId.Server) {
        updateServerRootComponents(batchJson, serverState);
      } else {
        this.updateWebAssemblyRootComponents(batchJson, webAssemblyState);
      }
    }

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Clear cached browser assets and republish so blazor.web.js matches the server runtime version exactly.
  2. Ensure the JS bundle is rebuilt whenever the server-side Blazor runtime is updated (run npm run build / publish the client assets together).
  3. If you added a custom rendermode, verify it maps to a known WebRendererId rather than an arbitrary integer.
  4. Check for stale CDN-cached blazor.web.js and bust the cache.
Defensive patterns

Strategy: validation

Validate before calling

import { WebRendererId } from '../Rendering/WebRendererId';
function isKnownRendererId(id: number): boolean {
  return id === WebRendererId.Server || id === WebRendererId.WebAssembly;
}

Type guard

function isKnownWebRendererId(id: unknown): id is WebRendererId {
  return id === WebRendererId.Server || id === WebRendererId.WebAssembly;
}

Prevention

When it happens

Trigger: A component's assignedRendererId is set to a value outside {Server, WebAssembly} (per the WebRendererId enum known to this JS client), and discoverNewState=true. The else branch of the Server/WebAssembly check fires.

Common situations: Version skew between the .NET server runtime (which may assign a new renderer enum value) and the shipped blazor.web.js (which only knows the old enum). Mixing a newer server build with an older cached/published JS bundle. Custom rendermode registrations that produce renderer IDs outside the known set.

Related errors


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