dotnet/aspnetcore · error
Descriptors must be assigned a renderer ID before getting us
Error message
Descriptors must be assigned a renderer ID before getting used as root components
What it means
Thrown inside refreshRootComponents() in WebRootComponentManager.ts:288 when a root component descriptor has a pending operation (add/update/remove) but its assignedRendererId is undefined. Root components are the top-level interactive components discovered from SSR markers; each must be bound to a concrete renderer (Server or WebAssembly) before any operation can be dispatched to that renderer. The manager cannot route an operation to a runtime that was never assigned.
Source
Thrown at src/Components/Web.JS/src/Services/WebRootComponentManager.ts:288
private refreshRootComponents(components: Iterable<RootComponentInfo>, discoverNewState = false) {
const operationsByRendererId = new Map<WebRendererId, RootComponentOperation[]>();
const rendererIds: Set<WebRendererId> = new Set<WebRendererId>();
for (const component of components) {
if (discoverNewState && component.assignedRendererId !== undefined) {
// Capture the renderer IDs for the available components to determine the
// effective render modes in the document for discovering new persisted state.
rendererIds.add(component.assignedRendererId);
}
const operation = this.determinePendingOperation(component);
if (!operation) {
continue;
}
const rendererId = component.assignedRendererId;
if (!rendererId) {
throw new Error('Descriptors must be assigned a renderer ID before getting used as root components');
}
let operations = operationsByRendererId.get(rendererId);
if (!operations) {
operations = [];
operationsByRendererId.set(rendererId, operations);
}
operations.push(operation);
}
let serverState = '';
let webAssemblyState = '';
if (discoverNewState) {
for (const rendererId of rendererIds) {
if (rendererId === WebRendererId.Server) {
// We have server components. Try to discover the persisted state for them
// and if there are no updates on this batch, push an empty set of operationsView on GitHub (pinned to 294cab2f9b)
Solutions
- Confirm you are not manually editing or injecting the component markers/blazor: component elements in the DOM that Blazor's SSR emits.
- Upgrade to the latest Blazor runtime — this invariant is enforced internally and bugs are fixed across releases.
- Reproduce minimally and file an issue with the rendered HTML at the moment of failure so the framework team can trace which descriptor lacked assignment.
- Avoid custom RootComponentManager/DescriptorHandler subclasses that bypass the assignedRendererId assignment step.
Defensive patterns
Strategy: validation
Type guard
function isRootComponentReady(c: RootComponentInfo): boolean {
return c.assignedRendererId !== undefined && c.assignedRendererId !== null;
} Prevention
- Do not hand-edit blazor component markers in the DOM.
- Keep server runtime and blazor.web.js versions in sync.
- Avoid subclassing RootComponentManager in ways that skip renderer assignment.
- Report internal invariant failures with the SSR HTML at failure time.
When it happens
Trigger: An internal code path calls determinePendingOperation(component) which returns a non-null operation, then reads component.assignedRendererId and finds it falsy. This indicates the descriptor reached the operation-dispatch phase before being activated/assigned a renderer — a framework-internal invariant violation rather than a normal user-actionable flow.
Common situations: Almost always an internal Blazor framework bug or a corrupted component-marker state on the page (e.g., hand-edited blazor markers, partially rendered SSR output, or a race between descriptor discovery and renderer attachment). Rarely seen in correctly generated apps; investigate if custom rendering pipeline or third-party SSR manipulation is present.
Related errors
- Could not resolve a root component with SSR component ID '${
- Invalid sequence number or identifier '${sequenceOrIdentifie
- initialParameters must be an object, even if empty.
- Dynamic root components have already been enabled.
- Dynamic root components have not been enabled in this applic
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/d7d902d4d090f580.
Report an issue: GitHub.