{"record":{"id":"92b6a75691b64edd","repo":"dotnet/aspnetcore","slug":"invalid-end-of-component-comment-json","errorCode":null,"errorMessage":"Invalid end of component comment: '${json}'","messagePattern":"Invalid end of component comment: '(.+?)'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts","lineNumber":288,"sourceCode":"    throw new Error('assembly must be defined when using a descriptor.');\n  }\n\n  if (!typeName) {\n    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;","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts#L270-L306","documentation":"Thrown by validateEndComponentPayload when the parsed end-of-component comment JSON has more or fewer than exactly one key. The end marker must contain only the single 'prerenderId' property; any extra or missing keys mean the payload is malformed. This is the first structural check on the closing marker before prerenderId is validated.","triggerScenarios":"An end component comment whose JSON has zero keys (empty object) or two+ keys; a transform that added/removed fields; a start marker accidentally used as an end marker.","commonSituations":"HTML minifier that strips or rewrites the end comment; a copy-paste error placing a start-comment payload where the end comment should be; version skew producing a different end-marker schema; corruption.","solutions":["Inspect the served HTML: the end comment must be a JSON object with exactly one key, prerenderId.","Remove HTML post-processing that alters Blazor comment JSON.","Ensure the prerendering pipeline emits the correct end marker shape.","Align server and client Blazor runtime versions."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function assertEndMarkerShape(payload: any) {\n  const keys = Object.keys(payload ?? {});\n  if (keys.length !== 1 || keys[0] !== 'prerenderId') {\n    throw new Error(`Invalid end marker; expected exactly { prerenderId }, got ${JSON.stringify(payload)}`);\n  }\n}","typeGuard":"function isEndMarker(p: any): p is { prerenderId: string } {\n  return p !== null && typeof p === 'object' && Object.keys(p).length === 1 && typeof p.prerenderId === 'string';\n}","tryCatchPattern":null,"preventionTips":["Ensure the prerendering pipeline emits end comments as { prerenderId } only.","Disable HTML transforms that alter comment JSON.","Validate end-marker shape in CI HTML assertions."],"tags":["blazor","prerendering","markers","validation","html"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}