{"record":{"id":"da7777aef6e5b6ef","repo":"leptos-rs/leptos","slug":"there-to-be-a-html-element","errorCode":null,"errorMessage":"there to be a <html> element","messagePattern":"there to be a <html> element","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"meta/src/html.rs","lineNumber":69,"sourceCode":"}\n\nstruct HtmlViewState<At>\nwhere\n    At: Attribute,\n{\n    attributes: At::State,\n}\n\nimpl<At> Render for HtmlView<At>\nwhere\n    At: Attribute,\n{\n    type State = HtmlViewState<At>;\n\n    fn build(self) -> Self::State {\n        let el = document()\n            .document_element()\n            .expect(\"there to be a <html> element\");\n\n        let attributes = self.attributes.build(&el);\n\n        HtmlViewState { attributes }\n    }\n\n    fn rebuild(self, state: &mut Self::State) {\n        self.attributes.rebuild(&mut state.attributes);\n    }\n}\n\nimpl<At> AddAnyAttr for HtmlView<At>\nwhere\n    At: Attribute,\n{\n    type Output<SomeNewAttr: Attribute> =\n        HtmlView<<At as NextAttribute>::Output<SomeNewAttr>>;\n","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/leptos-rs/leptos/blob/32d20f6c9d517451d77beb68d88c7716823dac41/meta/src/html.rs#L51-L87","documentation":"leptos_meta's <Html> component builds its view state by calling document().document_element() and unwrapping it, since the component only makes sense when rendering the root <html> element. If the document has no root element (i.e. we are not rendering into a real browser document, or the Html component was mounted somewhere other than a document root), the expect panics with this message. The library throws it because <Html> attributes (class, lang, etc.) can only be applied to the single <html> root.","triggerScenarios":"Mounting the <Html> component (or a component that uses it, like <MetaProvider>/routes with html attribute props) during client-side build/hydrate when document().document_element() returns None — e.g. running hydration code outside a browser environment, or the mount target replaced/removed the <html> element.","commonSituations":"Running WASM hydration in a non-browser context (tests without DOM, ssr-only code accidentally hydrated), mounting a Leptos app into a fragment detached from the document, or a custom root template missing <html>.","solutions":["Ensure the server-rendered template includes a real <html>...</html> root element so document_element() is populated on hydration.","Only render <Html> at the very root of the app (inside the hydration mount), not inside nested views or detached fragments.","Verify hydration is running in a browser (or browser-like test harness such as wasm-bindgen-test with a DOM), not in a headless JS-only environment without a document.","Check custom mount logic: if you replace document contents manually, keep the <html> element attached to the document."],"exampleFix":"// before: rendering Html inside a nested, detached view\nview! { <div><Html lang=\"en\"/></div> }\n\n// after: Html at the document root\nview! { <Html lang=\"en\"/> <App routes/> }","handlingStrategy":"validation","validationCode":"let has_root = web_sys::window()\n    .and_then(|w| w.document())\n    .and_then(|d| d.document_element())\n    .is_some();\nif !has_root { console_error!(\"<Html> requires a document with <html> root\"); return; }","typeGuard":"fn has_document_root() -> bool {\n    web_sys::window().map(|w| w.document()).flatten()\n        .and_then(|d| d.document_element()).is_some()\n}","tryCatchPattern":null,"preventionTips":["Render <Html> only at the app root inside a full browser document.","Keep <html>...</html> in the SSR shell intact.","Run hydration only in browser or DOM-equipped test environments."],"tags":["leptos","wasm","dom","hydration"],"backgroundTag":"missing-document-root-element","analyzedSha":"32d20f6c9d517451d77beb68d88c7716823dac41","analyzedAt":"2026-09-01T18:55:42.580Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}