{"record":{"id":"907e75e14d55e49e","repo":"yewstack/yew","slug":"a-resuming-component-must-have-a-suspense-ancestor","errorCode":null,"errorMessage":"a resuming component must have a Suspense ancestor","messagePattern":"a resuming component must have a Suspense ancestor","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/yew/src/html/component/lifecycle.rs","lineNumber":523,"sourceCode":"\n                let new_node_ref =\n                    bundle.reconcile(root, &scope, parent, sibling_slot.to_position(), new_vdom);\n                own_slot.reassign(new_node_ref);\n\n                let first_render = !self.has_rendered;\n                self.has_rendered = true;\n\n                if resuming_from_suspension {\n                    // The DOM we just reconciled still lives in the ancestor\n                    // Suspense's detached parent. The Suspense must process\n                    // the Resume message and re-render to shift children into\n                    // the live tree before our effects observe the DOM.\n                    // Hand the pending `rendered` to the Suspense; it will\n                    // re-schedule it once it fully un-suspends.\n                    let pending = PendingRendered::new(shared_state.clone(), first_render);\n                    let suspense_scope = scope\n                        .find_parent_scope::<BaseSuspense>()\n                        .expect(\"a resuming component must have a Suspense ancestor\");\n                    BaseSuspense::defer_rendered(&suspense_scope, self.comp_id, pending);\n                } else {\n                    scheduler::push_component_rendered(\n                        self.comp_id,\n                        Box::new(RenderedRunner {\n                            state: shared_state.clone(),\n                            first_render,\n                        }),\n                        first_render,\n                    );\n                }\n            }\n\n            #[cfg(feature = \"hydration\")]\n            ComponentRenderState::Hydration {\n                ref mut fragment,\n                ref parent,\n                ref mut own_slot,","sourceCodeStart":505,"sourceCodeEnd":541,"githubUrl":"https://github.com/yewstack/yew/blob/0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3/packages/yew/src/html/component/lifecycle.rs#L505-L541","documentation":"When a previously suspended component resumes and commits its render, Yew looks up its BaseSuspense ancestor again to hand over the pending rendered callback (BaseSuspense::defer_rendered). This expect fires when that ancestor is gone: the suspension was created under a <Suspense> that has since been unmounted, re-keyed, or re-created while the child was still suspended. It is an internal-consistency panic - the boundary that accepted the suspension is expected to still exist at resume time.","triggerScenarios":"Unmounting, re-keying, or conditionally removing the <Suspense> subtree while a child is still suspended (route change mid-load, a toggle flipping the boundary off); re-parenting the suspended component so its scope chain no longer reaches the original boundary.","commonSituations":"Router-driven page swaps where the boundary lives inside the swapped page; show.then(|| html!{<Suspense>...</Suspense>}) toggled during an async load; upgrading across Yew versions where suspense resume handling had bugs.","solutions":["Hoist the <Suspense> boundary above the conditional or router switch so it stays mounted while any child can suspend","Do not key or conditionally remount the boundary itself","Upgrade to the newest Yew patch release - suspense resume handling has received fixes","If it still reproduces on the latest version, file an issue with a minimal repro (suspension triggered while the boundary unmounts)"],"exampleFix":"// before: boundary is swapped out with the route while children still suspend\nhtml! { <Route>{ route_view }</Route> } // <Suspense> lives inside route_view\n\n// after: boundary outlives the switch\nhtml! {\n    <Suspense fallback={fallback()}>\n        <Route>{ route_view }</Route>\n    </Suspense>\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Hoist <Suspense> above route switches and conditionals so it stays mounted while children suspend","Never key or conditionally remount a Suspense boundary that has pending children","Stay on the latest Yew patch release; resume handling has been fixed over time"],"tags":["suspense","lifecycle","internal-invariant"],"backgroundTag":"missing-suspense-boundary","analyzedSha":"0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3","analyzedAt":"2026-08-22T21:16:31.212Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}