{"record":{"id":"98f58293f258a91f","repo":"dotnet/aspnetcore","slug":"root-components-cannot-be-marked-as-interactive-t","errorCode":null,"errorMessage":"Root components cannot be marked as interactive. The <html> element must be rendered statically so that scripts are not evaluated multiple times.","messagePattern":"Root components cannot be marked as interactive\\. The <html> element must be rendered statically so that scripts are not evaluated multiple times\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts","lineNumber":181,"sourceCode":"    } else {\n      return;\n    }\n  }\n}\n\nfunction parseCommentPayload(json: string): ServerComponentMarker | WebAssemblyComponentMarker | AutoComponentMarker {\n  const payload = JSON.parse(json);\n  const { type } = payload;\n  if (type !== 'server' && type !== 'webassembly' && type !== 'auto') {\n    throw new Error(`Invalid component type '${type}'.`);\n  }\n\n  return payload;\n}\n\nfunction assertNotDirectlyOnDocument(marker: Node) {\n  if (marker.parentNode instanceof Document) {\n    throw new Error('Root components cannot be marked as interactive. The <html> element must be rendered statically so that scripts are not evaluated multiple times.');\n  }\n}\n\nfunction getComponentEndComment(payload: ComponentMarker, start: Comment, iterator: ComponentCommentIterator): Comment | undefined {\n  const { prerenderId } = payload;\n  if (!prerenderId) {\n    return undefined;\n  }\n\n  while (iterator.next() && iterator.currentElement) {\n    const node = iterator.currentElement;\n    if (node.nodeType !== Node.COMMENT_NODE) {\n      continue;\n    }\n    if (!node.textContent) {\n      continue;\n    }\n","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts#L163-L199","documentation":"Thrown by assertNotDirectlyOnDocument (ComponentDescriptorDiscovery.ts:181) when a component marker's direct parent is the Document node itself — i.e. someone tried to make the <html> root element an interactive (Server/WebAssembly/Auto) component. Blazor requires the root <html> to remain static SSR so that <script> tags are not re-evaluated when interactive rendering re-renders the tree, which would double-load scripts and corrupt state.","triggerScenarios":"Registering a root component whose Razor output targets the document/html element with an interactive rendermode; App.razor or _Host equivalent placing an InteractiveServer/InteractiveAuto rendermode attribute such that the marker's parent resolves to Document; misconfigured Routes.razor with a rendermode on a component that wraps <html>.","commonSituations":"Migrating a legacy Blazor Server _Host.cshtml and accidentally applying @rendermode InteractiveServer at the document root; putting <HeadOutlet> or root components in a way that the top-level marker lands directly under document; custom IComponentRenderMode assignments on root components.","solutions":["Keep rendermode attributes off the root document layout; apply @rendermode only to nested components below <html>/<head>/<body>.","Render the app shell statically (SSR) and mark individual routable components or sub-trees as interactive.","Review App.razor / Routes.razor and ensure InteractiveServer/InteractiveAuto is on the Router content, not on a component that owns <html>.","If you need interactive head content, use <HeadOutlet> with an appropriate rendermode rather than re-rendering <html>."],"exampleFix":"<!-- before: App.razor root marked interactive -->\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head><component type=\"typeof(App)\" render-mode=\"InteractiveServer\" /></head>\n\n<!-- after: static shell, interactive router inside -->\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head><HeadOutlet /></head>\n  <body>\n    <Routes @rendermode=\"InteractiveServer\" />\n    <script src=\"_framework/blazor.web.js\"></script>\n  </body>\n</html>","handlingStrategy":"validation","validationCode":"function assertRootIsStatic(rootComponentType: string, renderMode?: string) {\n  if (renderMode && renderMode !== 'StaticServer' && rootComponentType === 'html') {\n    throw new Error('Do not apply an interactive rendermode to the document root.');\n  }\n}","typeGuard":"function isSafeRenderModeForRoot(mode: string | undefined): boolean {\n  return !mode || mode === 'StaticServer';\n}","tryCatchPattern":null,"preventionTips":["Keep rendermode attributes off <html>/document-level components.","Apply interactive rendermodes only to nested routable components.","Review App.razor / Routes.razor in code review."],"tags":["blazor","rendermode","root-component","ssr","document","scripts"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}