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

  1. Verify the payload was produced by the matching Cap'n Proto message type and deserializer function.
  2. Ensure publisher and subscriber use the same schema/version of the message definitions.
  3. Check payload integrity — confirm the bytes are complete and not truncated or corrupted in transit.
  4. 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

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.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/bf5cf9125b1bec16. Report an issue: GitHub.