nautechsystems/nautilus_trader · error
failed to decode Cap'n Proto {}: {}
Error message
failed to decode Cap'n Proto {}: {} What it means
Raised by the Cap'n Proto deserializer macro in the msgbus external codec when a message payload cannot be decoded into the target type. Reading the segments or the root may fail, but this specific error comes from the type's from_capnp conversion failing — the bytes were readable but did not represent a valid message of the expected type.
Source
Thrown at crates/common/src/msgbus/external/codec/capnp.rs:43
capnp::{FromCapnp, ToCapnp},
market_capnp,
};
use super::PayloadCodecError;
use crate::msgbus::BusPayloadType;
macro_rules! deserialize_payload_as {
($payload:expr, $type_name:expr, $ty:ty, $root:ty) => {{
let reader = ::capnp::serialize::read_message(
&mut &$payload[..],
::capnp::message::ReaderOptions::new(),
)
.context("failed to read Cap'n Proto message")?;
let root = reader
.get_root::<$root>()
.with_context(|| format!("Cap'n Proto payload has no {} root", $type_name))?;
<$ty>::from_capnp(root)
.map_err(|e| anyhow::anyhow!("failed to decode Cap'n Proto {}: {}", $type_name, e))
}};
}
macro_rules! define_deserializer {
($fn_name:ident, $ty:ty, $type_name:literal, $root:ty) => {
pub(crate) fn $fn_name(payload: &[u8]) -> anyhow::Result<$ty> {
deserialize_payload_as!(payload, $type_name, $ty, $root)
}
};
}
define_deserializer!(
deserialize_order_book_deltas,
OrderBookDeltas,
"OrderBookDeltas",
market_capnp::order_book_deltas::Reader
);
define_deserializer!(View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the payload was produced by the matching Cap'n Proto message type and deserializer function.
- Ensure publisher and subscriber use the same schema/version of the message definitions.
- Check payload integrity — confirm the bytes are complete and not truncated or corrupted in transit.
- Regenerate codec code from the current .capnp schema files if definitions changed.
Defensive patterns
Strategy: try-catch
Try / catch
match deserialize_order_book_delta(payload) {
Ok(msg) => handle(msg),
Err(e) if e.to_string().contains("failed to decode Cap'n Proto") => {
log::warn!("dropping undecodable capnp payload: {e:#}");
// inspect schema versions / route to dead-letter queue
}
Err(e) => return Err(e),
} Prevention
- Keep Cap'n Proto schemas in lockstep between publisher and consumer.
- Tag or envelope messages with a type identifier so the correct deserializer is chosen.
- Pin message schema versions in interop tests between nautilus versions.
- Check payload integrity (length, framing) before handing bytes to the codec.
When it happens
Trigger: Feeding a payload produced by a different message type or schema version into the generated deserialize_<type> function; truncated or corrupted payloads; decoding a payload from a peer running an incompatible schema.
Common situations: Schema drift between publisher and subscriber after a message definition change; routing the wrong byte stream to a codec; interop between different nautilus versions with changed Cap'n Proto definitions.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Cap'n Proto decoding requires the `capnp` feature
- failed to decode SBE {type_name}: {e}
- Cap'n Proto encoding is not supported for Redis cache payloa
- Instances must have encode_record_batch_py method
- Failed to send order updated event: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/bf5cf9125b1bec16.
Report an issue: GitHub.