nautechsystems/nautilus_trader · error · anyhow::Error
unknown broker client order ID signal byte '{}'
Error message
unknown broker client order ID signal byte '{}' What it means
Decoding a broker-prefixed client order ID: the first byte after the prefix must be one of the known signal bytes (O-format, UUID, or raw variants). The observed byte matches none of them, so the payload format is unrecognizable.
Source
Thrown at crates/adapters/binance/src/common/encoder.rs:263
Ok(unpack_o_format(packed, signal == SIGNAL_O_HYPHENS))
}
SIGNAL_UUID_HYPHENS | SIGNAL_UUID_NO_HYPHENS => {
anyhow::ensure!(
data.len() == UUID_B62_LEN,
"invalid UUID broker client order ID payload length"
);
let value = decode_base62(data).context("invalid UUID broker client order ID")?;
Ok(format_uuid(value, signal == SIGNAL_UUID_HYPHENS))
}
SIGNAL_RAW => {
let raw = std::str::from_utf8(data).context("invalid raw broker client order ID")?;
anyhow::ensure!(
!raw.is_empty(),
"missing raw broker client order ID payload"
);
Ok(raw.to_string())
}
_ => anyhow::bail!(
"unknown broker client order ID signal byte '{}'",
signal as char
),
}
}
fn build_encoded(prefix: &str, signal: u8, b62: &[u8]) -> String {
let mut result = String::with_capacity(prefix.len() + 1 + b62.len());
result.push_str(prefix);
result.push(signal as char);
// base62 output is always valid ASCII
result.push_str(std::str::from_utf8(b62).expect("base62 is valid UTF-8"));
result
}
fn encode_base62<const N: usize>(mut value: u128) -> [u8; N] {
let mut buf = [b'0'; N];
for i in (0..N).rev() {View on GitHub (pinned to a4b06ed870)
Solutions
- Configure a longer, distinctive broker_id so unrelated IDs never share the prefix
- Upgrade the reading side to the adapter version that produced the IDs (new signal bytes appear with format extensions)
- If the ID genuinely is not yours, treat it as an opaque external ID instead of decoding
Example fix
// before
match decode_broker_id_checked(encoded, broker_id) {
Ok(cid) => cid,
Err(e) => return Err(e),
}
// after: unknown signal -> opaque raw ID, keep processing updates
let cid = decode_broker_id_checked(encoded, broker_id)
.unwrap_or_else(|_| encoded.to_string()); Defensive patterns
Strategy: fallback
Validate before calling
const KNOWN_SIGNALS: &[u8] = b"oOuUw"; // however the adapter spells them - mirror encoder constants
fn has_known_signal(id: &str, prefix: &str) -> bool {
id.strip_prefix(prefix)
.and_then(|p| p.as_bytes().first())
.is_none_or(|b| KNOWN_SIGNALS.contains(b))
} Type guard
fn is_adapter_generated_id(id: &str, prefix: &str) -> bool {
id.strip_prefix(prefix)
.and_then(|p| p.as_bytes().first())
.is_some_and(|b| KNOWN_SIGNALS.contains(b))
} Try / catch
let cid = match decode_broker_id_checked(encoded, broker_id) {
Ok(decoded) => ClientOrderId::new_checked(decoded)?,
Err(_) => {
// unknown signal -> assume foreign exchange-generated ID, use verbatim
ClientOrderId::new(encoded)
}
}; Prevention
- Prefer long unique broker IDs over short defaults
- When reading orders back from Binance, accept that exchange-appended IDs may not be yours and handle them opaquely
- Keep encoder and decoder in the same crate version - new signal bytes only exist in newer versions
When it happens
Trigger: Any clientOrderId that starts with the broker prefix but continues with a byte the encoder never emits - foreign exchange-generated IDs, user-supplied IDs, or a payload format introduced in a newer adapter version than the decoder.
Common situations: Broker prefix configured so short (1-2 chars) that Binance's own appended IDs (e.g. autoclose/conditional suffixes) begin with it; reading orders created by a newer adapter; hand-built IDs.
Related errors
- missing broker client order ID signal
- invalid O-format broker client order ID payload length
- invalid UUID broker client order ID payload length
- missing raw broker client order ID payload
- {standard_key_var} not found in config or environment
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/36ea95dc5fc1a4a6.
Report an issue: GitHub.