{"record":{"id":"ea5f2c7cd61c3266","repo":"dotnet/aspnetcore","slug":"could-not-find-an-end-component-comment-for-sta","errorCode":null,"errorMessage":"Could not find an end component comment for '${start}'.","messagePattern":"Could not find an end component comment for '(.+?)'\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts","lineNumber":211,"sourceCode":"    if (node.nodeType !== Node.COMMENT_NODE) {\n      continue;\n    }\n    if (!node.textContent) {\n      continue;\n    }\n\n    const definition = blazorCommentRegularExpression.exec(node.textContent);\n    const json = definition && definition[1];\n    if (!json) {\n      continue;\n    }\n\n    validateEndComponentPayload(json, prerenderId);\n\n    return node as Comment;\n  }\n\n  throw new Error(`Could not find an end component comment for '${start}'.`);\n}\n\nlet nextUniqueDescriptorId = 0;\n\nfunction createServerComponentComment(payload: ServerComponentMarker, start: Comment, end: Comment | undefined): ServerComponentDescriptor {\n  validateServerComponentPayload(payload);\n\n  return {\n    ...payload,\n    uniqueId: nextUniqueDescriptorId++,\n    start,\n    end,\n  };\n}\n\nfunction createWebAssemblyComponentComment(payload: WebAssemblyComponentMarker, start: Comment, end: Comment | undefined): WebAssemblyComponentDescriptor {\n  validateWebAssemblyComponentPayload(payload);\n","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts#L193-L229","documentation":"Thrown by getComponentEndComment after walking siblings of the start comment and finding no matching end comment for the given prerenderId. Prerendered components are bracketed by a start comment and an end comment carrying the same prerenderId; if the iterator exhausts siblings without the closing marker, the DOM is considered broken and discovery fails.","triggerScenarios":"The <!--Blazor:{...prerenderId...}--> start marker exists but its matching end comment was removed, reordered, or never emitted; an HTML transformation split the component region; streaming SSR truncated before the end comment.","commonSituations":"HTML minifier/post-processor that drops 'redundant' comments; a partial render that emitted only the opening marker; a layout that conditionally renders and cuts the component boundary; caching that captured only part of the prerendered output.","solutions":["Inspect the served HTML: confirm both start and end Blazor comments are present and carry the same prerenderId.","Disable any HTML post-processing that strips comments between prerender start and end.","Ensure the full prerendered response is flushed (no truncation).","Re-check that the component tree is balanced (no conditional that opens a marker without closing it).","Align server and client runtime versions."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function assertPairedMarkers(html: string) {\n  const starts = (html.match(/<!--Blazor:[^{]*{\"type\"/g) || []).length;\n  // end comments carry prerenderId only\n  if (starts === 0) return;\n  // ensure each start has a matching end by prerenderId (simplified)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure prerender output flushes both start and end comments.","Disable HTML transforms that strip comments.","Keep component boundaries balanced in layouts.","Verify full HTML in DevTools source view."],"tags":["blazor","prerendering","markers","html","ssr"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}