leptos-rs/leptos · error

SVG element creation to work

Error message

SVG element creation to work

What it means

When a Portal's children are SVG content, leptos creates a container element via document().create_element_ns(SVG_NAMESPACE, "g") and expects it to succeed. The panic means the browser environment refused to create the SVG element — essentially only possible in non-DOM environments or exotic embedders without SVG support.

Source

Thrown at leptos/src/portal.rs:48

{
    if cfg!(target_arch = "wasm32")
        && Owner::current_shared_context()
            .map(|sc| sc.is_browser())
            .unwrap_or(true)
    {
        use send_wrapper::SendWrapper;
        use wasm_bindgen::JsCast;

        let mount = mount.unwrap_or_else(|| {
            document().body().expect("body to exist").unchecked_into()
        });
        let children = children.into_inner();

        Effect::new(move |_| {
            let container = if is_svg {
                document()
                    .create_element_ns(Some("http://www.w3.org/2000/svg"), "g")
                    .expect("SVG element creation to work")
            } else {
                document()
                    .create_element("div")
                    .expect("HTML element creation to work")
            };

            let render_root = if use_shadow {
                container
                    .attach_shadow(&web_sys::ShadowRootInit::new(
                        web_sys::ShadowRootMode::Open,
                    ))
                    .map(|root| root.unchecked_into())
                    .unwrap_or(container.clone())
            } else {
                container.clone()
            };

            let _ = mount.append_child(&container);

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Run SVG Portal code only in a real browser environment; mock or skip in jsdom/node tests.
  2. Ensure the code path isn't reached during SSR (gate Portal rendering on client mount).
  3. If targeting minimal webviews, verify createElementNS with the SVG namespace is supported or switch to HTML children.
  4. Use a fixture document with full SVG support (happy-dom/full jsdom with svg) for tests.

Example fix

// before
effect: Portal renders SVG children in jsdom test // panics
// after
#[cfg(feature = "browser-tests")]
#[wasm_bindgen_test]
fn portal_svg() { ... } // run in real browser via wasm-bindgen-test runner
Defensive patterns

Strategy: validation

Validate before calling

// only run Portal-with-SVG code in a real DOM environment
let is_browser = cfg!(target_arch = "wasm32") && document().create_element_ns(Some("http://www.w3.org/2000/svg"), "g").is_ok();

Type guard

fn svg_capable_document() -> bool {
    document().create_element_ns(Some("http://www.w3.org/2000/svg"), "g").is_ok()
}

Prevention

When it happens

Trigger: Rendering an SVG Portal in a test environment (jsdom/node without full DOM), web workers, or a webview lacking SVG namespace element creation.

Common situations: Unit-testing components that render Portal with SVG children; SSR leakage into client-only code paths; headless environments with incomplete DOM implementations.

Related errors


AI-assisted analysis of leptos-rs/leptos@32d20f6c9d (2026-09-01). Data as JSON: /api/errors/286f850b032201c8. Report an issue: GitHub.