dotnet/aspnetcore · error
End of component comment prerendered property must match the
Error message
End of component comment prerendered property must match the start comment prerender id: '${prerenderId}', '${prerenderEndId}' What it means
Thrown by validateEndComponentPayload (ComponentDescriptorDiscovery.ts:295) when the end marker's prerenderId does not equal the start marker's prerenderId. Blazor pairs prerendered components by matching these IDs; a mismatch means start and end comments got out of order (e.g. interleaved or duplicated markers).
Source
Thrown at src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts:295
// Parameter definitions and values come Base64 encoded from the server, since they contain random data and can make the
// comment invalid. We could unencode them in .NET Code, but that would be slower to do and we can leverage the fact that
// JS provides a native function that will be much faster and that we are doing this work while we are fetching
// blazor.boot.json
payload.parameterDefinitions = payload.parameterDefinitions && atob(payload.parameterDefinitions);
payload.parameterValues = payload.parameterValues && atob(payload.parameterValues);
}
function validateEndComponentPayload(json: string, prerenderId: string): void {
const payload = JSON.parse(json) as ComponentEndMarker;
if (Object.keys(payload).length !== 1) {
throw new Error(`Invalid end of component comment: '${json}'`);
}
const prerenderEndId = payload.prerenderId;
if (!prerenderEndId) {
throw new Error(`End of component comment must have a value for the prerendered property: '${json}'`);
}
if (prerenderEndId !== prerenderId) {
throw new Error(`End of component comment prerendered property must match the start comment prerender id: '${prerenderId}', '${prerenderEndId}'`);
}
}
class ComponentCommentIterator {
private childNodes: NodeListOf<ChildNode>;
private currentIndex: number;
private length: number;
public currentElement: ChildNode | undefined;
public constructor(childNodes: NodeListOf<ChildNode>) {
this.childNodes = childNodes;
this.currentIndex = -1;
this.length = childNodes.length;
}
View on GitHub (pinned to 294cab2f9b)
Solutions
- Inspect the raw HTML to verify each start <!--Blazor:{...prerenderId...}--> is immediately followed by its matching <!--Blazor:{prerenderId:'<same id>'}-->.
- Disable HTML comment reordering/minification on Blazor pages.
- Match framework versions.
- Avoid caching prerendered fragments in a way that re-orders markers.
Defensive patterns
Strategy: validation
Validate before calling
function markersArePaired(startPayload: {prerenderId?:string}, endPayload: {prerenderId?:string}): boolean {
return !!startPayload?.prerenderId && startPayload.prerenderId === endPayload?.prerenderId;
} Type guard
function isMatchingEnd(startId: string, endPayload: any): boolean {
return endPayload?.prerenderId === startId;
} Prevention
- Do not reorder HTML comments on Blazor pages.
- Avoid caching prerender fragments out of order.
- Match framework versions so prerenderId formats agree.
When it happens
Trigger: A start marker's prerenderId differs from the next end marker encountered while iterating; caused by reordered/duplicated prerendered component comments in the DOM.
Common situations: HTML reordering by minifiers/transformers; nested prerendered components whose comments got interleaved incorrectly; duplicated cached prerender fragments; version mismatch in prerenderId format.
Related errors
- Invalid end of component comment: '${json}'
- End of component comment must have a value for the prerender
- Could not find an end component comment for '${start}'.
- Found malformed component comment at ${candidateStart.textCo
- Invalid component type '${type}'.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/6323b286d6e537c7.
Report an issue: GitHub.