leptos-rs/leptos · error

no shared context

Error message

no shared context

What it means

During SSR streaming of a Suspense component (to_html_async_with_buf), when a local resource resolves and the chunk must be marked incomplete, leptos fetches the global shared reactive context via Owner::current_shared_context().expect(...). The panic means serialization was invoked with no shared context installed — i.e. to_html/render-to-string was called without leptos' reactive runtime being set up.

Source

Thrown at leptos/src/suspense_component.rs:451

        let mut fut = Box::pin(ScopedFuture::new(ErrorHookFuture::new(
            async move {
                // race the local resource notifier against the set of tasks
                //
                // if there are local resources, we just return the fallback immediately
                //
                // otherwise, we want to wait for resources to load before trying to resolve the body
                //
                // this is *less efficient* than just resolving the body
                // however, it means that you can use reactive accesses to resources/async derived
                // inside component props, at any level, and have those picked up by Suspense, and
                // that it will wait for those to resolve
                select! {
                    // if there are local resources, bail
                    // this will only have fired by this point for local resources accessed
                    // *synchronously*
                    _ = local_rx => {
                        let sc = Owner::current_shared_context().expect("no shared context");
                        sc.set_incomplete_chunk(self.id);
                        if let Some(tx) =
                            notify_error_boundary.write_value().take()
                        {
                            let _ = tx.send(());
                        }
                        None
                    }
                    _ = tasks_rx => {
                        let children = {
                            let mut children_lock = children.lock().or_poisoned();
                            children_lock.take().expect("children should not be removed until we render here")
                        };

                        // if we ran this earlier, reactive reads would always be registered as None
                        // this is fine in the case where we want to use Suspend and .await on some future
                        // but in situations like a <For each=|| some_resource.snapshot()/> we actually
                        // want to be able to 1) synchronously read a resource's value, but still 2) wait

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Use leptos' official server-rendering APIs (leptos_axum::render_route / render_to_string etc.) which install the shared context.
  2. If serializing manually, create the runtime first (e.g. create_scope + Owner::with, or leptos' to_html entry points that set it up).
  3. In tests, wrap serialization in run_scope/with the shared context created by leptos helpers.
  4. Check you haven't spawned the serialization into a task that lost the owner; enter the owner inside the task.

Example fix

// before
let html = suspense.to_html_async_with_buf(...); // no shared context
// after
let html = leptos::ssr::render_to_string(|cx| view! { cx, <Suspense>...</Suspense> }).await;
Defensive patterns

Strategy: validation

Validate before calling

// before custom SSR serialization, ensure the shared context exists
assert!(leptos::Owner::current_shared_context().is_some(), "run inside leptos SSR entry points");

Type guard

fn shared_context_ready() -> bool {
    leptos::Owner::current_shared_context().is_some()
}

Prevention

When it happens

Trigger: Calling to_html_async_with_buf (or a Suspense's HTML serializer) manually outside leptos' runtime setup; custom server integration that skips the owner/context initialization; using render helpers outside an act of set_global context.

Common situations: Custom axum/actix integrations not going through leptos' official server rendering entry points; tests that serialize Suspense views without creating a runtime; library code reusing the internal serializer in a fresh task.

Related errors


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