iced-rs/iced · critical

Append canvas to HTML body

Error message

Append canvas to HTML body

What it means

On wasm32, after obtaining the window canvas the runtime appends it to the document body and expects the DOM append_child call to succeed. append_child returns an Err (HierarchyRequestError or similar) when the body element is missing or the node cannot be attached; iced cannot display anything without the canvas in the DOM, so it panics.

Source

Thrown at winit/src/lib.rs:374

                                    let document = window.document().unwrap();
                                    let body = document.body().unwrap();

                                    let target = target.and_then(|target| {
                                        body.query_selector(&format!("#{target}"))
                                            .ok()
                                            .unwrap_or(None)
                                    });

                                    match target {
                                        Some(node) => {
                                            let _ = node.replace_with_with_node_1(&canvas).expect(
                                                &format!("Could not replace #{}", node.id()),
                                            );
                                        }
                                        None => {
                                            let _ = body
                                                .append_child(&canvas)
                                                .expect("Append canvas to HTML body");
                                        }
                                    };
                                }

                                self.process_event(
                                    event_loop,
                                    Event::WindowCreated {
                                        id,
                                        window: Arc::new(window),
                                        exit_on_close_request,
                                        make_visible: visible,
                                        on_open,
                                    },
                                );
                            }
                            Control::Exit => {
                                self.process_event(event_loop, Event::Exit);
                                event_loop.exit();

View on GitHub (pinned to d146509d89)

Solutions

  1. Load the wasm entry point after the DOM is ready: use <script type="module">, defer, or wait for the load event before calling the iced runner.
  2. Ensure the HTML document has a valid <body> element at startup.
  3. If a #container node lookup fails upstream, verify the element id in HTML matches what the app queries before the append_child fallback runs.
  4. Pin compatible iced/winit versions; the DOM mounting logic changed across releases.

Example fix

// before (html)
<head><script src="app.js"></script></head>
// after (html)
<body><script type="module" src="app.js"></script></body>
Defensive patterns

Strategy: validation

Validate before calling

// only mount after the document body exists
if (document.readyState === "loading") {
  await new Promise(r => document.addEventListener("DOMContentLoaded", r));
}
if (!document.body) throw new Error("document.body missing; cannot mount canvas");

Type guard

function bodyReady(): boolean {
  return document.readyState !== "loading" && document.body !== null;
}

Try / catch

try {
  body.appendChild(canvas);
} catch (e) {
  console.error("Canvas mount failed; is <body> present and parsed?", e);
}

Prevention

When it happens

Trigger: Calling run on wasm when document.body() is None (script executed before <body> exists or in a non-HTML context), or when the canvas node cannot be a child of body (wrong node type/already-attached hierarchy issue).

Common situations: WASM module loaded in <head> without defer, so body doesn't exist yet; using a custom loader that runs before the document finishes parsing; page contexts where body was replaced during startup.

Related errors


AI-assisted analysis of iced-rs/iced@d146509d89 (2026-09-11). Data as JSON: /api/errors/3938b609cb852853. Report an issue: GitHub.