nautechsystems/nautilus_trader · error · anyhow::Error
CustomData registry returned non-custom data
Error message
CustomData registry returned non-custom data
What it means
decode_custom_data_value looks up a registered custom data type and expects the registry to return a Data::Custom variant. If the decoded Data carries any other variant, the internal registry/decoder contract is broken and the code bails. This guards an internal invariant between the CustomData envelope type and the decoded payload.
Source
Thrown at crates/common/src/msgbus/external/mod.rs:591
) -> anyhow::Result<Option<CustomData>> {
let Some(data) = deserialize_custom_from_json(custom_type_name.as_str(), value)? else {
log::warn!(
"External custom payload type '{custom_type_name}' is not registered for inbound republishing"
);
return Ok(None);
};
let envelope_type_name = value
.get("type")
.and_then(serde_json::Value::as_str)
.context("CustomData JSON missing 'type' field")?;
anyhow::ensure!(
envelope_type_name == custom_type_name.as_str(),
"CustomData envelope type '{envelope_type_name}' does not match message type '{custom_type_name}'"
);
let Data::Custom(custom) = data else {
anyhow::bail!("CustomData registry returned non-custom data");
};
Ok(Some(custom))
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the registered decoder for the type name in the preceding ensure! check and confirm it constructs Data::Custom.
- Re-register the custom type with the correct decoder so the registry round-trips CustomData.
- Check that publisher and consumer use matching versions of the custom data type definition.
Defensive patterns
Strategy: try-catch
Validate before calling
// before decoding, confirm the registered decoder for this type name is the custom one
if let Some(decoder) = registry.get(&type_name) {
assert!(decoder.produces_custom_data(), "decoder for {type_name} must yield Data::Custom");
} Type guard
fn is_custom(data: &Data) -> bool { matches!(data, Data::Custom(_)) } Try / catch
match decode_custom_data_payload(&payload, ®istry) {
Ok(Some(custom)) => handle(custom),
Ok(None) => {},
Err(e) => log::error!("custom data decode failed: {e}"),
} Prevention
- Keep custom type registrations in one module so decoders cannot be shadowed.
- Round-trip test every registered custom type (serialize then decode) in unit tests.
- Pin matching versions of custom data definitions across publisher and consumer.
When it happens
Trigger: Calling decode_custom_data_payload on a payload whose registered decoder returns a Data value that is not Data::Custom — i.e. the envelope type name matched a custom type name but the decoded value deserialized into a non-custom variant.
Common situations: A custom data type was re-registered or shadowed so its decoder resolves to a built-in Data variant; version skew between a publisher serializing CustomData and a consumer whose registry maps the type name to different code; hand-written decoders registered for type names that collide with core types.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Custom data type "{type_name}" is already registered for JSO
- No tearsheet chart registered under '{chart_name}'.{hint} Re
- Theme '{name}' not found.{suggestion_text} Available themes:
- Theme name cannot be empty
- Binance Futures custom data requires BINANCE venue instrumen
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/06ae0aa190595d20.
Report an issue: GitHub.