dotnet/aspnetcore · error · Error
End of component comment prerendered property must match…
Error message
End of component comment prerendered property must match the start comment prerender id: '${prerenderId}', '${prerenderEndId}' What it means
Blazor pairs each prerendered component's start and end HTML comments via a shared 'prerenderId'. This error fires when an end marker's prerenderId does not equal the start marker's prerenderId for the same component region, meaning the comment stream is desynchronized. It is a guard against corrupt or reordered component boundaries produced during SSR or by intermediate HTML processing.
Solutions
- Disable HTML minification/comment-stripping middleware and any CDN HTML optimization on Blazor routes.
- Clear any partial/cached HTML fragments (output cache, response cache, CDN) and reproduce on a clean response.
- Confirm the Blazor JS bundle and server runtime are the same framework version.
- Inspect the rendered HTML around the failing component to verify start and end comments share one prerenderId.
Example fix
// before: cached fragment mixes component A's start marker with component B's end marker // after: disable response caching/varied-by for prerendered component pages [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, VaryByHeader = "*")]
Defensive patterns
Strategy: validation
Validate before calling
// Pair start/end markers by prerenderId before processing
function markersMatch(start: { prerenderId?: string }, end: { prerenderId?: string }): boolean {
return !!start.prerenderId && start.prerenderId === end.prerenderId;
} Type guard
function hasMatchingPrerenderId(a: unknown, b: unknown, id: string): boolean {
return !!a && !!b && (a as any).prerenderId === id && (b as any).prerenderId === id;
} Prevention
- Disable HTML rewriting/minification that can reorder comment nodes.
- Do not cache partial prerendered fragments.
- Keep client and server Blazor versions aligned.
- When building custom hosts, preserve all Blazor comment markers in document order.
When it happens
Trigger: Thrown at line 295 when prerenderEndId !== prerenderId, i.e. the end comment carries a different prerenderId than the start comment passed into validateEndComponentPayload. Happens when start/end comment pairs get split, reordered, or duplicated.
Common situations: An HTML minifier/rewriter that moves, duplicates, or merges comment nodes; a caching layer serving a stale fragment of one component inside another's boundaries; concurrent prerender of nested components producing interleaved markers that get reassembled incorrectly; version skew between server-side renderer and the JS that consumes markers.
Related errors
- End of component comment must have a value for the…
- Could not find an end component comment for
- Found malformed component comment at
- Root components cannot be marked as interactive. The
- assembly must be defined when using a descriptor.
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/6323b286d6e537c7.
Report an issue: GitHub.
Appendix: 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 3600ca084e)