DioxusLabs/dioxus · error
Failed to serialize SSE event
Error message
Failed to serialize SSE event
What it means
ServerEvents::from_stream maps every item of the user's TryStream through axum's Event::json_data. json_data returns Err when serde_json cannot serialize the event (custom Serialize impls that fail, maps with non-string keys, invalid nested payloads) and the closure unwraps it with expect, so one bad event panics the stream task.
Source
Thrown at packages/fullstack/src/payloads/sse.rs:318
Self {
_marker: std::marker::PhantomData,
client: None,
keep_alive: Some(KeepAlive::new().interval(Duration::from_secs(15))),
sse: Some(sse),
}
}
/// Create a `ServerEvents` from a `TryStream` of events.
pub fn from_stream<S>(stream: S) -> Self
where
S: TryStream<Ok = T, Error = BoxError> + Send + 'static,
T: Serialize,
{
let stream = stream.map_ok(|event| {
axum::response::sse::Event::default()
.json_data(event)
.expect("Failed to serialize SSE event")
});
let sse = axum::response::Sse::new(stream.boxed());
Self {
_marker: std::marker::PhantomData,
client: None,
keep_alive: Some(KeepAlive::new().interval(Duration::from_secs(15))),
sse: Some(sse),
}
}
/// Set the keep-alive configuration for the SSE connection.
///
/// A `None` value will disable the default `KeepAlive` of 15 seconds.
pub fn with_keep_alive(mut self, keep_alive: Option<KeepAlive>) -> Self {
self.keep_alive = keep_alive;
self
}
View on GitHub (pinned to 393d190a80)
Solutions
- Fix the event type: use string keys (HashMap<String, _>, BTreeMap) and derive Serialize where possible
- Pre-test representative events with serde_json::to_string before wiring them into the stream
- For dynamic payloads, send pre-serialized JSON via ServerEvents::new + SseTx instead of from_stream
- Add unit tests that serialize every event variant the stream can emit
Example fix
// before
let events = ServerEvents::from_stream(
stream.map_ok(|ev: HashMap<u32, String>| ev), // non-string keys -> serde_json error
);
// after
let events = ServerEvents::from_stream(
stream.map_ok(|ev: HashMap<String, String>| ev),
); Defensive patterns
Strategy: validation
Validate before calling
// Smoke-test the event type before wiring the stream:
fn can_serialize<T: Serialize>(event: &T) -> bool {
serde_json::to_string(event).is_ok()
}
assert!(can_serialize(&sample_event)); Try / catch
// Send pre-serialized events via SseTx, handling failures explicitly:
ServerEvents::new(move |tx| async move {
while let Some(ev) = rx.next().await {
match serde_json::to_string(&ev) {
Ok(json) => { tx.send(json); }
Err(e) => { tracing::error!("skipping unserializable event: {e}"); }
}
}
}) Prevention
- Derive Serialize on event types instead of hand-written impls
- Use string keys in maps sent over SSE
- Add serialization round-trip tests for every event variant
- For dynamic payloads, stream pre-serialized strings instead of typed values
When it happens
Trigger: Streaming a type T through ServerEvents::from_stream where T's Serialize errors at runtime: HashMap<u32, _> or other non-string-keyed maps, hand-written Serialize impls returning Err, or types that encode invalid JSON in edge cases.
Common situations: Server-function SSE endpoints returning dynamic/aggregate payloads; switching an event struct to a map keyed by numeric ids; custom Serialize impls that can fail on edge-case state.
Related errors
- Failed to parse index.html from public directory
- Failed to create new router after hot-patch!
- Lazy value is not initialized. Make sure to call `initialize
- protocols is an invalid header value
- todo: convert_resize_data in dioxus-native. requires support
AI-assisted analysis of DioxusLabs/dioxus@393d190a80 (2026-08-16).
Data as JSON: /api/errors/e9aa2f960d899889.
Report an issue: GitHub.