{"record":{"id":"345cd9cce2fb78b4","repo":"dotnet/aspnetcore","slug":"end-of-component-comment-must-have-a-value-for-the","errorCode":null,"errorMessage":"End of component comment must have a value for the prerendered property: '${json}'","messagePattern":"End of component comment must have a value for the prerendered property: '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts","lineNumber":292,"sourceCode":"    throw new Error('typeName must be defined when using a descriptor.');\n  }\n\n  // Parameter definitions and values come Base64 encoded from the server, since they contain random data and can make the\n  // comment invalid. We could unencode them in .NET Code, but that would be slower to do and we can leverage the fact that\n  // JS provides a native function that will be much faster and that we are doing this work while we are fetching\n  // blazor.boot.json\n  payload.parameterDefinitions = payload.parameterDefinitions && atob(payload.parameterDefinitions);\n  payload.parameterValues = payload.parameterValues && atob(payload.parameterValues);\n}\n\nfunction validateEndComponentPayload(json: string, prerenderId: string): void {\n  const payload = JSON.parse(json) as ComponentEndMarker;\n  if (Object.keys(payload).length !== 1) {\n    throw new Error(`Invalid end of component comment: '${json}'`);\n  }\n  const prerenderEndId = payload.prerenderId;\n  if (!prerenderEndId) {\n    throw new Error(`End of component comment must have a value for the prerendered property: '${json}'`);\n  }\n  if (prerenderEndId !== prerenderId) {\n    throw new Error(`End of component comment prerendered property must match the start comment prerender id: '${prerenderId}', '${prerenderEndId}'`);\n  }\n}\n\nclass ComponentCommentIterator {\n  private childNodes: NodeListOf<ChildNode>;\n\n  private currentIndex: number;\n\n  private length: number;\n\n  public currentElement: ChildNode | undefined;\n\n  public constructor(childNodes: NodeListOf<ChildNode>) {\n    this.childNodes = childNodes;\n    this.currentIndex = -1;","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts#L274-L310","documentation":"Thrown by validateEndComponentPayload (ComponentDescriptorDiscovery.ts:292) when an end marker JSON has exactly one key but that key is not 'prerenderId' (or prerenderId is falsy). The end marker must carry the prerenderId to pair with its start marker.","triggerScenarios":"End comment JSON like {\"foo\":\"bar\"} — single key but wrong name; or {\"prerenderId\":null} / empty string.","commonSituations":"Custom end-marker emission with a wrong key name; version mismatch; JSON rewrite that renamed the field.","solutions":["Confirm the end comment JSON key is exactly 'prerenderId' with a non-empty value.","Use framework marker generation; match versions.","Inspect raw HTML end comment."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function endMarkerHasPrerenderId(json: string): boolean {\n  try {\n    const p = JSON.parse(json);\n    return !!p?.prerenderId;\n  } catch { return false; }\n}","typeGuard":"function hasPrerenderId(payload: any): payload is { prerenderId: string } {\n  return typeof payload?.prerenderId === 'string' && payload.prerenderId.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Emit end markers with exactly the prerenderId key.","Use framework marker generation; pin versions.","Inspect raw HTML end comments."],"tags":["blazor","ssr","prerendering","markers","validation"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}