yewstack/yew · error
no body node found
Error message
no body node found
What it means
Renderer::new()/with_props defaults to mounting into gloo::utils::document().body(); this expect fires when document.body is null at the moment the Renderer is constructed. That means the entry code ran before the HTML body was parsed, or executes in an environment that simply has no body element. It is a bootstrap-order problem, not a rendering failure.
Source
Thrown at packages/yew/src/renderer.rs:80
Self::default()
}
/// Creates a [Renderer] that renders into a custom root with default properties.
pub fn with_root(root: Element) -> Self {
Self::with_root_and_props(root, Default::default())
}
}
impl<COMP> Renderer<COMP>
where
COMP: BaseComponent + 'static,
{
/// Creates a [Renderer] that renders into the document body with custom properties.
pub fn with_props(props: COMP::Properties) -> Self {
Self::with_root_and_props(
gloo::utils::document()
.body()
.expect("no body node found")
.into(),
props,
)
}
/// Creates a [Renderer] that renders into a custom root with custom properties.
pub fn with_root_and_props(root: Element, props: COMP::Properties) -> Self {
Self { root, props }
}
/// Renders the application.
pub fn render(self) -> AppHandle<COMP> {
set_default_panic_hook();
AppHandle::<COMP>::mount_with_props(self.root, Rc::new(self.props))
}
}
#[cfg(feature = "hydration")]View on GitHub (pinned to 0e4a05472f)
Solutions
- Add defer to the script tag, or move it to the end of <body>
- Defer construction and render until DOMContentLoaded fires
- Mount into an explicit existing element with Renderer::with_root(document().get_element_by_id("app").unwrap())
- In tests, make sure the harness document actually contains a <body>
Example fix
// before: runs immediately; if the script is in <head>, body does not exist yet
#[wasm_bindgen(start)]
fn start() {
yew::Renderer::<App>::new().render();
}
// after: mount into a known element, with the script deferred or at the end of <body>
#[wasm_bindgen(start)]
fn start() {
let root = gloo::utils::document()
.get_element_by_id("app")
.expect("missing #app mount point");
yew::Renderer::<App>::with_root(root).render();
} Defensive patterns
Strategy: validation
Validate before calling
// Guard before constructing the default Renderer:
match gloo::utils::document().body() {
Some(_) => yew::Renderer::<App>::new().render(),
None => {
// body not parsed yet - defer or fail with a clear message
}
} Prevention
- Load the bundle with defer or place the script at the end of <body>
- Prefer an explicit mount element via Renderer::with_root
- In tests, ensure the DOM fixture includes a <body> element
When it happens
Trigger: Constructing Renderer inside #[wasm_bindgen(start)] or module-level code while the script loads in <head> without defer (body not yet parsed); running the CSR entry in a DOM host without a body element (bare test harnesses, workers).
Common situations: Bundler or framework templates that move the script into <head>; removing defer/type=module attributes; hydration entries that run during initial parse; headless tests using minimal document fixtures.
Related errors
- failed to create detached element
- invalid attribute key
- could not set property
- could not remove attribute
- could not remove property
AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22).
Data as JSON: /api/errors/d06b5b04c8bbe646.
Report an issue: GitHub.