{"record":{"id":"c5528f7cee49ef49","repo":"yewstack/yew","slug":"to-suspend-rendering-a-suspense-component-is","errorCode":null,"errorMessage":"To suspend rendering, a <Suspense /> component is required.","messagePattern":"To suspend rendering, a <Suspense /> component is required\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/yew/src/html/component/lifecycle.rs","lineNumber":461,"sourceCode":"    fn suspend(&mut self, shared_state: &Shared<Option<ComponentState>>, suspension: Suspension) {\n        // Currently suspended, we re-use previous root node and send\n        // suspension to parent element.\n\n        if suspension.resumed() {\n            // schedule a render immediately if suspension is resumed.\n            scheduler::push_component_render(\n                self.comp_id,\n                Box::new(RenderRunner {\n                    state: shared_state.clone(),\n                }),\n            );\n        } else {\n            // We schedule a render after current suspension is resumed.\n            let comp_scope = self.inner.any_scope();\n\n            let suspense_scope = comp_scope\n                .find_parent_scope::<BaseSuspense>()\n                .expect(\"To suspend rendering, a <Suspense /> component is required.\");\n\n            let comp_id = self.comp_id;\n            let shared_state = shared_state.clone();\n            suspension.listen(Callback::from(move |_| {\n                scheduler::push_component_render(\n                    comp_id,\n                    Box::new(RenderRunner {\n                        state: shared_state.clone(),\n                    }),\n                );\n                scheduler::start();\n            }));\n\n            if let Some(ref last_suspension) = self.suspension {\n                if &suspension != last_suspension {\n                    // We remove previous suspension from the suspense.\n                    BaseSuspense::resume(&suspense_scope, last_suspension.clone());\n                }","sourceCodeStart":443,"sourceCodeEnd":479,"githubUrl":"https://github.com/yewstack/yew/blob/0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3/packages/yew/src/html/component/lifecycle.rs#L443-L479","documentation":"When a component's render yields a suspension (use_prepared_state, use_transitive_state, or anything returning SuspensionResult), Yew walks up the scope tree via find_parent_scope::<BaseSuspense>() to register the suspension with the nearest Suspense boundary. This expect fires when no <Suspense> component exists above the suspending component: suspending is only legal inside a boundary that can display a fallback while the component waits.","triggerScenarios":"A component calling use_prepared_state/use_transitive_state (or otherwise producing Err(Suspension) from render) that is mounted without a <Suspense> ancestor - e.g. directly at the app root, on a router page that forgot the boundary, or where the Suspense is behind a flag that is false on the first render.","commonSituations":"Adding a data-fetching suspense hook during CSR-only development where no boundary was ever needed; restructuring the tree so the boundary ends up below the suspending component; conditionally rendering the <Suspense> itself.","solutions":["Wrap the suspending component (usually the page/route component) in <Suspense fallback={...}>","Ensure the boundary exists from the very first render, not added in a later pass","If no fallback UI is wanted, replace the suspense-based hook with plain use_state plus an effect-driven fetch","Check every consumer of the hook, including components rendered through routers or portals"],"exampleFix":"// before: use_prepared_state inside UserProfile, no boundary above it\nhtml! { <UserProfile /> }\n\n// after\nhtml! {\n    <Suspense fallback={html! { <p>{ \"Loading...\" }</p> }}>\n        <UserProfile />\n    </Suspense>\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat any suspense-returning hook as requiring a <Suspense> ancestor - wrap page components by default","Mount the boundary on the first render; never add it conditionally later","When adding use_prepared_state to an existing component, immediately check its ancestors for a boundary"],"tags":["suspense","lifecycle","use-prepared-state","hydration"],"backgroundTag":"missing-suspense-boundary","analyzedSha":"0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3","analyzedAt":"2026-08-22T21:16:31.212Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}