dotnet/aspnetcore · error · Error

End of component comment must have a value for the…

Error message

End of component comment must have a value for the prerendered property: '${json}'

What it means

Blazor emits special HTML comments as start/end markers around prerendered components, and the end marker must be a JSON object containing exactly a 'prerenderId' field that pairs it with its start marker. This error is thrown by validateEndComponentPayload when the parsed end-marker JSON has no truthy 'prerenderId' property (e.g. it is missing, empty, null, or undefined). It indicates the SSR-rendered marker payload is malformed and Blazor cannot pair the component's prerender boundaries.

Solutions

  1. Disable any HTML minification/compression or response-rewriting middleware that alters comment contents and re-test.
  2. Verify the Blazor JS bundle version (blazor.web.js) exactly matches the server framework version producing the markers.
  3. Inspect the raw HTML response for the component end comment and confirm it contains a JSON payload like {"prerenderId":"<id>"}.
  4. If hosting behind a CDN/reverse proxy, bypass it to confirm it is not stripping comments or rewriting payloads.

Example fix

// before: end marker rendered as <!-- --> (empty) due to a minifier
// after: preserve Blazor's markers verbatim in the response pipeline
// e.g. disable HTML minification on the Blazor endpoint:
services.AddHtmlMinification(o => o.MinifyComments = false);
// or exclude Blazor routes from the minifying middleware.
Defensive patterns

Strategy: validation

Validate before calling

// Before relying on a prerendered component marker, validate its shape
function isValidEndMarker(json: string): boolean {
  try {
    const p = JSON.parse(json);
    return p && typeof p.prerenderId === 'string' && p.prerenderId.length > 0;
  } catch { return false; }
}
// if (!isValidEndMarker(payloadJson)) { /* surface a friendlier error / disable enhancement */ }

Type guard

function isComponentEndMarker(v: unknown): v is { prerenderId: string } {
  return typeof v === 'object' && v !== null
    && typeof (v as any).prerenderId === 'string'
    && (v as any).prerenderId.length > 0;
}

Prevention

When it happens

Trigger: Triggered when ComponentDescriptorDiscovery parses an end-of-component comment whose JSON body lacks a prerenderId value (fails the !prerenderEndId check at line 293). Occurs after Object.keys(payload).length === 1 already passed, so the payload is a single-key object but that key is not a populated 'prerenderId'.

Common situations: A custom or hand-edited host page that strips/alters Blazor comment markers; an output-filtering middleware (HTML minifiers, response compressors, CDNs) that rewrites comment payloads; a mismatched Blazor server JS version vs. the blazor.web.js/blazor.server.js bundle; partial HTML caching that drops the prerenderId.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/345cd9cce2fb78b4. Report an issue: GitHub.

Appendix: source

Thrown at src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts:292

    throw new Error('typeName must be defined when using a descriptor.');
  }

  // 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;

View on GitHub (pinned to 3600ca084e)