yewstack/yew · error
failed to deserialize state
Error message
failed to deserialize state
What it means
With use_prepared_state, the server serializes state and embeds it base64-encoded in the HTML; during hydration the client rebuilds a data:application/octet-binary;base64,... URL, fetch()es it, and decodes the bytes (decode_base64 in feat_hydration.rs). This expect fires at that first step - the fetch/decode of the data URL fails. Since Yew itself generated the payload, a failure means the HTML was altered between SSR and hydration (attributes stripped, re-escaped, or truncated) or the environment blocks data: fetches.
Source
Thrown at packages/yew/src/functional/hooks/use_prepared_state/feat_hydration.rs:91
let data = use_state(|| {
let (s, handle) = Suspension::new();
(
SuspensionResult::<(Option<Rc<T>>, Option<Rc<D>>)>::Err(s),
Some(handle),
)
})
.run(ctx);
let state = {
let data = data.clone();
ctx.next_prepared_state(move |_re_render, buf| -> PreparedStateBase<T, D> {
if let Some(buf) = buf {
let buf = format!("data:application/octet-binary;base64,{buf}");
spawn_local(async move {
let buf = decode_base64(&buf)
.await
.expect("failed to deserialize state");
let ((state, deps), _) =
bincode::serde::decode_from_slice::<(Option<T>, Option<D>), _>(
&buf,
bincode::config::standard(),
)
.map(|((state, deps), consumed)| {
((state.map(Rc::new), deps.map(Rc::new)), consumed)
})
.expect("failed to deserialize state");
data.set((Ok((state, deps)), None));
});
}
PreparedStateBase {
#[cfg(feature = "ssr")]
state: None,View on GitHub (pinned to 0e4a05472f)
Solutions
- View the served page source and confirm the attribute containing application/octet-binary;base64 is present and intact
- Allow data: in the CSP directives governing fetch (e.g. connect-src data:) or restructure how state is transferred
- Disable attribute minification/re-escaping in the HTML pipeline between SSR and hydration
- Purge cached SSR HTML after each deploy so server output and client bundle always come from the same build
Defensive patterns
Strategy: validation
Validate before calling
// Before hydrate(), confirm the serialized state survived your HTML pipeline:
let html = gloo::utils::document()
.document_element()
.expect("no document element")
.outer_html();
assert!(
html.contains("application/octet-binary;base64"),
"prepared-state marker was stripped by HTML post-processing"
); Prevention
- Allow data: URLs in the CSP fetch directives when using use_prepared_state
- Do not minify or re-escape attributes of SSR output between server and client
- Deploy SSR server and client bundle together and purge HTML caches on deploy
When it happens
Trigger: Hydrating HTML whose embedded base64 state attribute was mangled by a minifier or template engine that re-escapes attributes; a Content-Security-Policy that does not allow data: URLs for fetch; proxies or CDNs truncating very long attributes; cached SSR HTML that no longer matches the deployed client bundle.
Common situations: Post-processing SSR output (minify/sanitize steps) between server and client; strict CSP rollouts; edge caches serving stale pages across deploys; intermediaries rewriting data: URLs.
Related errors
- failed to clone node.
- failed to prepare state
- To suspend rendering, a <Suspense /> component is required.
- this hook takes 2 arguments but 1 argument was supplied
- this hook takes 2 arguments but 1 argument was supplied
AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22).
Data as JSON: /api/errors/35b30e1975657ef6.
Report an issue: GitHub.