yewstack/yew · error

failed to create detached element

Error message

failed to create detached element

What it means

When a Suspense bundle attaches (packages/yew/src/dom_bundle/bsuspense.rs:90), Yew creates a detached <div> via document().create_element to host suspended children off-tree while the fallback shows in place, and unwraps the result with .expect. createElement("div") can only fail with an InvalidCharacterError, which cannot happen for the fixed valid name 'div' in a real browser — so in practice this panic indicates the code is running against a missing or non-functional DOM implementation.

Source

Thrown at packages/yew/src/dom_bundle/bsuspense.rs:90

impl Reconcilable for VSuspense {
    type Bundle = BSuspense;

    fn attach(
        self,
        root: &BSubtree,
        parent_scope: &AnyScope,
        parent: &Element,
        slot: DomSlot,
    ) -> (DomSlot, Self::Bundle) {
        let VSuspense {
            children,
            fallback,
            suspended,
            key,
        } = self;
        let detached_parent = document()
            .create_element("div")
            .expect("failed to create detached element");

        // When it's suspended, we render children into an element that is detached from the dom
        // tree while rendering fallback UI into the original place where children resides in.
        if suspended {
            let (_child_ref, children_bundle) =
                children.attach(root, parent_scope, &detached_parent, DomSlot::at_end());
            let (fallback_ref, fallback) = fallback.attach(root, parent_scope, parent, slot);
            (
                fallback_ref,
                BSuspense {
                    children_bundle,
                    fallback: Some(Fallback::Bundle(fallback)),
                    detached_parent,
                    key,
                },
            )
        } else {
            let (child_ref, children_bundle) = children.attach(root, parent_scope, parent, slot);

View on GitHub (pinned to 0e4a05472f)

Solutions

  1. Run suspense-touching tests under a real DOM: wasm_bindgen_test with the browser test runner, or a complete DOM shim
  2. Make sure SSR does not render the client bundle — gate client-only rendering with cfg(target_arch = "wasm32") and the SSR entry with the ssr feature
  3. Update wasm-bindgen/web-sys if the environment shim is incomplete, since the panic is environmental, not a Yew bug

Example fix

// before (test runs without a DOM)
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_node_experimental);

// after (run in a real browser DOM)
// wasm_bindgen_test_configure!(run_in_browser);  // default under the browser test runner
Defensive patterns

Strategy: validation

Validate before calling

// before mounting client code, confirm a functional DOM exists
if web_sys::window().is_none() {
    // do not run component rendering here
    return;
}

Type guard

fn has_dom() -> bool { web_sys::window().is_some_and(|w| w.document().is_some()) }

Prevention

When it happens

Trigger: Running the client bundle in an environment whose global document cannot create elements (a bare wasm runtime, a unit-test harness without a browser DOM, or a partially mocked web-sys).

Common situations: Running component tests outside wasm-bindgen-test's browser runner; accidentally executing the client (wasm) suspense code path inside an SSR process with a stub DOM; broken js/wasm runtime initialization where window/document globals are absent.

Related errors


AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22). Data as JSON: /api/errors/e0e90a5a9456e058. Report an issue: GitHub.