nautechsystems/nautilus_trader · error
Invalid payload kind format: {stream_msg:?}
Error message
Invalid payload kind format: {stream_msg:?} What it means
The optional payload-kind header (PAYLOAD_KIND_FIELD) must be a BulkString, and after UTF-8 decoding it must equal PAYLOAD_KIND_TYPED. A non-BulkString value raises this 'Invalid payload kind format' error before the value check (which would yield 'Unknown payload kind').
Source
Thrown at crates/infrastructure/src/redis/msgbus.rs:848
anyhow::bail!("Invalid topic format: {stream_msg:?}");
};
topic = Some(
String::from_utf8(bytes.clone())
.map_err(|e| anyhow::anyhow!("Error parsing topic: {e}"))?,
);
}
b"type" => {
let redis::Value::BulkString(bytes) = &pair[1] else {
anyhow::bail!("Invalid type format: {stream_msg:?}");
};
type_name = Some(
String::from_utf8(bytes.clone())
.map_err(|e| anyhow::anyhow!("Error parsing type: {e}"))?,
);
}
key if key == PAYLOAD_KIND_FIELD.as_bytes() => {
let redis::Value::BulkString(bytes) = &pair[1] else {
anyhow::bail!("Invalid payload kind format: {stream_msg:?}");
};
let value = std::str::from_utf8(bytes)
.map_err(|e| anyhow::anyhow!("Error parsing payload kind: {e}"))?;
anyhow::ensure!(
value == PAYLOAD_KIND_TYPED,
"Unknown payload kind '{value}'"
);
typed_payload = true;
}
b"encoding" => {
let redis::Value::BulkString(bytes) = &pair[1] else {
anyhow::bail!("Invalid encoding format: {stream_msg:?}");
};
let value = std::str::from_utf8(bytes)
.map_err(|e| anyhow::anyhow!("Error parsing encoding: {e}"))?;
encoding = value
.parse()
.map_err(|e| anyhow::anyhow!("Error parsing encoding: {e}"))?;View on GitHub (pinned to 18893faf8b)
Solutions
- Write the payload-kind field using the library's constant (PAYLOAD_KIND_TYPED) rather than a custom value
- Omit the payload-kind field for legacy (untyped) messages instead of sending an invalid marker
- Align producer and consumer library versions so both use the same payload-kind field name and constant
- Inspect the raw entry to confirm the stored value, then XDEL the malformed entry
Example fix
// before
redis.xadd(stream, "*", &[("payload_kind", 1)]);
// after
redis.xadd(stream, "*", &[("payload_kind", "typed")]); // matches PAYLOAD_KIND_TYPED Defensive patterns
Strategy: validation
Validate before calling
const PAYLOAD_KIND_TYPED: &str = "typed"; // match library constant
fn payload_kind_ok(entry: &redis::Value) -> bool {
matches!(entry, redis::Value::Array(f) if f.chunks(2).all(|c|
!matches!(&c[0], redis::Value::BulkString(k) if k == b"payload_kind") || matches!(c[1], redis::Value::BulkString(_))))
} Try / catch
match decode_bus_message(&entry) {
Err(e) if e.to_string().contains("payload kind") => {
log::warn!("unrecognized payload kind header, skipping: {e}");
}
other => other?,
} Prevention
- Use the library's PAYLOAD_KIND_FIELD/PAYLOAD_KIND_TYPED constants in producers
- Omit the header for legacy untyped messages instead of inventing values
- Keep producer and consumer crate versions in lockstep
When it happens
Trigger: A stream entry whose payload-kind field value is not a byte string — a producer writing a numeric or malformed kind marker instead of the expected typed-payload constant.
Common situations: Producers using an incompatible/older message format with a different kind encoding; hand-written stream entries; test data built with wrong redis::Value variants.
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
- Invalid topic format: {stream_msg:?}
- Invalid type format: {stream_msg:?}
- Invalid encoding format: {stream_msg:?}
- Invalid hash index payload for '{index_key}': expected field
- heartbeat_interval_secs must be greater than 0
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/9e070c73b050e627.
Report an issue: GitHub.