leptos-rs/leptos · error
You cannot use Suspend on an attribute outside Suspense
Error message
You cannot use Suspend on an attribute outside Suspense
What it means
Same family as the class variant: a Suspend-wrapped style attribute value is a future, and to_html can only render values available synchronously via now_or_never(). Outside a Suspense context there is nothing to await the future, so the style attribute panics during HTML string generation.
Source
Thrown at tachys/src/reactive_graph/style.rs:515
style_reactive!(ArcStore, <V>, V, false, ArcStore<V>: Get<Value = V>);
style_reactive!(ArcField, <V>, V, false, ArcField<V>: Get<Value = V>);
}
/*
impl<Fut> IntoStyle for Suspend<Fut>
where
Fut: Clone + Future + Send + 'static,
Fut::Output: IntoStyle,
{
type AsyncOutput = Fut::Output;
type State = Rc<RefCell<Option<<Fut::Output as IntoStyle>::State>>>;
type Cloneable = Self;
type CloneableOwned = Self;
fn to_html(self, style: &mut String) {
if let Some(inner) = self.inner.now_or_never() {
inner.to_html(style);
} else {
panic!("You cannot use Suspend on an attribute outside Suspense");
}
}
fn hydrate<const FROM_SERVER: bool>(
self,
el: &crate::renderer::types::Element,
) -> Self::State {
let el = el.to_owned();
let state = Rc::new(RefCell::new(None));
reactive_graph::spawn_local_scoped({
let state = Rc::clone(&state);
async move {
*state.borrow_mut() =
Some(self.inner.await.hydrate::<FROM_SERVER>(&el));
self.subscriber.forward();
}
});
stateView on GitHub (pinned to 32d20f6c9d)
Solutions
- Wrap the view containing the async style attribute in <Suspense>.
- Precompute the style value so it is synchronous at render time.
- Move the async fetch above the render (e.g. load data in a resource awaited within Suspense and pass the plain string down).
Example fix
// before
view! { <div style=Suspend(async move { theme_style().await }) /> }
// after
view! {
<Suspense fallback=|| ()>
<div style=Suspend(async move { theme_style().await }) />
</Suspense>
} Defensive patterns
Strategy: validation
Validate before calling
fn style_ready(s: &Suspend<impl Future>) -> bool { s.clone().inner_now_or_never().is_some() } // if false, you need Suspense Type guard
fn is_plain_style(v: &str) -> bool { true } // favor &str/Read-derived styles over Suspend Try / catch
std::panic::catch_unwind(|| to_html(&view)).map_err(|_| /* wrap in Suspense and retry */)
Prevention
- Wrap async style attributes in a Suspense boundary.
- Resolve theme/style data before the initial SSR render.
- Keep inline styles synchronous during SSR.
- Add an SSR smoke test that renders every component to HTML.
When it happens
Trigger: Using Suspend(async expression) as a style attribute during SSR/dry rendering without a surrounding Suspense boundary.
Common situations: Async-computed inline styles (theme data fetched async) rendered on the server; converting a style: attr to an async source without adding Suspense.
Related errors
- You cannot use Suspend on an attribute outside Suspense
- Reading from a LocalResource outside Suspense in `ssr` mode
- no shared context
- children should not be removed until we render here
- Failed to find the route {path} requested by the user. This
AI-assisted analysis of leptos-rs/leptos@32d20f6c9d (2026-09-01).
Data as JSON: /api/errors/2f358729f68428b9.
Report an issue: GitHub.