tracel-ai/burn · error
Can deserialize messages from the websocket.
Error message
Can deserialize messages from the websocket.
What it means
This panic occurs in download_tensor when deserializing a websocket message with rmp_serde (MessagePack) into ExternalCommMessage fails, or when the deserialized message is not the Tensor variant. It indicates protocol desynchronization: the peer sent bytes that are not a valid tensor response — a different burn/protocol version, corrupt frame, or a foreign message type on this connection.
Source
Thrown at crates/burn-communication/src/external_comm.rs:167
// Send the download request with the download id
let bytes: bytes::Bytes =
rmp_serde::to_vec(&ExternalCommMessage::TensorRequest(transfer_id))
.unwrap()
.into();
stream
.send(Message::new(bytes))
.await
.expect("Failed to send download id");
if let Ok(msg) = stream.recv().await {
let Some(msg) = msg else {
log::warn!("Received None message from the websocket, closing connection.");
return None;
};
let ExternalCommMessage::Tensor(data) = rmp_serde::from_slice(&msg.data)
.expect("Can deserialize messages from the websocket.")
else {
panic!("Message should have been TensorData")
};
return Some(data);
}
log::warn!("Closed connection");
None
}
/// Get the WebSocket stream for the given address, or create a new one if it doesn't exist.
async fn get_data_stream(
&self,
address: Address,
) -> Arc<Mutex<<P::Client as ProtocolClient>::Channel>> {
let mut streams = self.channels.lock().await;
match streams.get(&address) {
Some(stream) => stream.clone(),
None => {View on GitHub (pinned to d16f7ba2ed)
Solutions
- Ensure all peers run the same burn/burn-communication version so ExternalCommMessage encodes identically.
- Log and return None (treat as failed download) instead of panicking on unexpected message types.
- Inspect the raw bytes of the failing frame to confirm whether it is corrupt or a different message variant.
- Check for proxies/middleware that could alter binary websocket frames (disable permessage-deflate mismatches, ensure binary framing).
Example fix
// before
let ExternalCommMessage::Tensor(data) = rmp_serde::from_slice(&msg.data)
.expect("Can deserialize messages from the websocket.")
else { panic!("Message should have been TensorData") };
// after
match rmp_serde::from_slice::<ExternalCommMessage>(&msg.data) {
Ok(ExternalCommMessage::Tensor(data)) => return Some(data),
Ok(other) => log::warn!("unexpected message {other:?}"),
Err(e) => log::warn!("deserialization failed: {e}"),
}
return None; Defensive patterns
Strategy: type-guard
Type guard
fn as_tensor_msg(bytes: &[u8]) -> Option<ExternalCommMessage> {
match rmp_serde::from_slice::<ExternalCommMessage>(bytes) {
Ok(ExternalCommMessage::Tensor(d)) => Some(ExternalCommMessage::Tensor(d)),
_ => None,
}
} Try / catch
let Some(ExternalCommMessage::Tensor(data)) = as_tensor_msg(&msg.data) else {
log::warn!("non-tensor/corrupt frame received");
return None;
}; Prevention
- Pin identical burn versions across all communicating nodes.
- Verify transports preserve binary websocket frames (no lossy proxies).
- Negotiate a protocol version in the handshake.
When it happens
Trigger: Receiving a message from a peer running a different burn-communication version with a changed ExternalCommMessage enum; the data channel delivering interleaved/misrouted frames; truncated or corrupted MessagePack payloads on a flaky connection.
Common situations: Mixed-version cluster where nodes were upgraded independently; middleware/proxy mangling binary frames; two servers sharing a websocket channel with mismatched message expectations.
Related errors
- Message should have been TensorData
- Received a message that wasn't a tensor request! {msg:?}
- Failed to open remote 'data' channel to {address}: {err:?}.
- Failed to receive message from websocket: {err:?}
- no fusion optimization named `{}` is registered; register it
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/1aa99bb7954aa0cf.
Report an issue: GitHub.