nautechsystems/nautilus_trader · error

Unknown typed payload '{type_name}'

Error message

Unknown typed payload '{type_name}'

What it means

For typed messages (payload_kind set to the typed marker), the `type` header is resolved through BusPayloadType::from_typed_name, which returns None for names that do not correspond to a known typed payload. This error is raised so consumers fail fast rather than silently treating an unknown type as custom. Untyped messages with unknown names are instead wrapped as BusPayloadType::Custom.

Source

Thrown at crates/infrastructure/src/redis/msgbus.rs:886

            b"payload" => {
                let redis::Value::BulkString(bytes) = &pair[1] else {
                    anyhow::bail!("Invalid payload format: {stream_msg:?}");
                };
                payload = Some(Bytes::copy_from_slice(bytes));
            }
            _ => {}
        }
    }

    let Some(topic) = topic else {
        anyhow::bail!("Stream message missing topic: {stream_msg:?}");
    };
    let Some(payload) = payload else {
        anyhow::bail!("Stream message missing payload: {stream_msg:?}");
    };
    let payload_type = match type_name {
        Some(type_name) if typed_payload => BusPayloadType::from_typed_name(&type_name)
            .ok_or_else(|| anyhow::anyhow!("Unknown typed payload '{type_name}'"))?,
        Some(type_name) => BusPayloadType::from_name(&type_name),
        None if typed_payload => {
            anyhow::bail!("Typed stream message missing type: {stream_msg:?}")
        }
        None => BusPayloadType::Custom(Ustr::default()),
    };

    Ok(BusMessage::with_str_topic(
        topic,
        payload_type,
        payload,
        encoding,
    ))
}

async fn run_heartbeat(
    heartbeat_interval_secs: u16,
    signal: Arc<AtomicBool>,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Identify the unknown type_name in the error and add/upgrade the corresponding payload type in the consumer's BusPayloadType registry.
  2. Align publisher and consumer crate versions so both know the typed payload names.
  3. If the payload is genuinely custom, publish without the typed payload_kind marker so it maps to BusPayloadType::Custom.

Example fix

// before: consumer without the new type
// publisher sends type "Data.v2.CustomTick"
// after: upgrade both sides to a crate version where
// BusPayloadType::from_typed_name("Data.v2.CustomTick") resolves, or
// publish with legacy (untyped) headers.
Defensive patterns

Strategy: validation

Validate before calling

// verify typed names resolve before publishing
assert!(BusPayloadType::from_typed_name(&type_name).is_some(),
        "unknown typed payload: {type_name}");

Try / catch

match decode_bus_message(entry) {
    Ok(m) => handle(m),
    Err(e) if e.to_string().starts_with("Unknown typed payload") => {
        log::error!("publisher knows a type this consumer does not: {e}");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: stream_messages -> decode_bus_message processes a message with typed payload kind whose `type` name has no match in BusPayloadType::from_typed_name.

Common situations: Publisher upgraded with new message types while the consumer runs an older crate version; a custom producer emits a made-up typed name; cross-instance deployments where type registries differ.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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