yewstack/yew · error

failed to prepare state

Error message

failed to prepare state

What it means

On the SSR path, use_prepared_state serializes (state, deps) with bincode so the value can be embedded in the page for hydration; this expect fires when that encode returns an error. Bincode only fails when the serde Serialize impl itself errors or the value cannot be represented - typical cases are custom Serialize impls returning Err for edge-case data and non-finite floats, which bincode's standard configuration rejects.

Source

Thrown at packages/yew/src/functional/hooks/use_prepared_state/mod.rs:136

        #[cfg(feature = "hydration")]
        pub has_buf: bool,
        pub _marker: PhantomData<(T, D)>,
    }

    impl<T, D> PreparedState for PreparedStateBase<T, D>
    where
        D: Serialize + DeserializeOwned + PartialEq + 'static,
        T: Serialize + DeserializeOwned + 'static,
    {
        #[cfg(feature = "ssr")]
        fn prepare(&self) -> String {
            use base64ct::{Base64, Encoding};

            let state = bincode::serde::encode_to_vec(
                (self.state.as_deref(), self.deps.as_deref()),
                bincode::config::standard(),
            )
            .expect("failed to prepare state");

            Base64::encode_string(&state)
        }
    }
}

#[cfg(any(feature = "hydration", feature = "ssr"))]
use feat_any_hydration_ssr::PreparedStateBase;

View on GitHub (pinned to 0e4a05472f)

Solutions

  1. Add a unit test that bincode-encodes realistic values of T and D (same call as the hook) and run it in CI
  2. Fix or replace the failing custom serde impls; prefer derived Serialize/Deserialize
  3. Sanitize non-finite floats (map to 0.0 or a string) before they enter prepared state
  4. Keep prepared state to plain data - numbers, strings, Vec, HashMap - and do complex computation in components

Example fix

// before: NaN slips into prepared state, bincode rejects it
let price = Price { value: input.unwrap_or(f64::NAN) };

// after: sanitize before the hook encodes it
let price = Price { value: input.filter(|v| v.is_finite()).unwrap_or(0.0) };

// CI guard mirroring the hook's encode:
#[test]
fn prepared_state_encodes() {
    let bytes = bincode::serde::encode_to_vec(
        (Some(Price { value: 0.0 }), Some(())),
        bincode::config::standard(),
    );
    assert!(bytes.is_ok());
}
Defensive patterns

Strategy: validation

Validate before calling

// Mirror the hook's encode in CI so bad types fail at test time, not in SSR:
#[test]
fn prepared_state_encodes() {
    let bytes = bincode::serde::encode_to_vec(
        (Some(sample_state()), Some(sample_deps())),
        bincode::config::standard(),
    );
    assert!(bytes.is_ok());
}

Prevention

When it happens

Trigger: use_prepared_state with a T or deps D containing a hand-written Serialize impl that returns an error for some values, NaN/Infinity floats, or constructs that bincode's standard config cannot encode - so SSR works locally but panics on production data.

Common situations: Custom Serialize/Deserialize impls for domain types; sensor or financial data containing NaN/infinite values; state types that grew unsupported constructs over time.

Related errors


AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22). Data as JSON: /api/errors/48bdeb381de4a39c. Report an issue: GitHub.