nautechsystems/nautilus_trader · error
missing broker client order ID signal
Error message
missing broker client order ID signal
What it means
Binance order IDs are round-tripped through a compact encoding: an optional broker prefix followed by a one-byte 'signal' byte identifying the payload format (hyphenated UUID, non-hyphenated, etc.). decode_broker_id_checked found the prefix but then hit an empty payload — no signal byte at all — so it cannot determine the format and bails.
Solutions
- Check the original order ID for truncation — Binance caps newClientOrderId length; ensure encoded IDs fit within the limit before submitting.
- Regenerate the order ID with the encoder and resubmit; do not attempt to decode the corrupted value.
- Guard decode calls with a length check (payload after prefix must be >= 1 byte) to give a clearer failure upstream.
- Verify the ID was produced by this adapter's encoder and not mixed with IDs from another integration.
Example fix
// before
let Some((&signal, data)) = payload.as_bytes().split_first() else {
anyhow::bail!("missing broker client order ID signal");
};
// after: validate length at encode time so this cannot occur
anyhow::ensure!(
encoded.len() <= MAX_BINANCE_CLIENT_ORDER_ID_LEN,
"encoded client order ID exceeds Binance limit: {}",
encoded.len()
); Defensive patterns
Strategy: validation
Validate before calling
fn is_decodable_broker_id(id: &str, prefix: &str) -> bool {
id.strip_prefix(prefix).map_or(false, |p| !p.is_empty())
} Try / catch
match decode_client_order_id(&encoded) {
Ok(id) => id,
Err(e) if e.to_string().contains("missing broker client order ID signal") => {
eprintln!("order ID truncated: {encoded}");
encoded.to_string()
}
Err(e) => return Err(e),
} Prevention
- Keep encoded client order IDs within Binance's newClientOrderId length cap so nothing is truncated.
- Never hand-assemble prefixed IDs; always go through the encoder.
- Log full IDs before sending so truncation can be diagnosed after the fact.
When it happens
Trigger: Calling decode_broker_id or decode_client_order_id on a string that consists of exactly the broker prefix (e.g. "x-NAU-") with nothing after it — typically a truncated or corrupted order ID, often after the exchange truncated a long newClientOrderId on the wire.
Common situations: Binance truncating client order IDs that exceed its length limit, cutting off the encoded payload; hand-editing or logging/marshalling bugs that clip the ID string; using an ID produced by a different encoder version.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- unknown broker client order ID signal byte
- Failed to advance balances group
- invalid O-format broker client order ID payload length
- missing raw broker client order ID payload
- 16 lowercase hex bytes are valid TradeId
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/aab728af78d3a67b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/adapters/binance/src/common/encoder.rs:235
/// Returns an error if the broker-prefixed encoding is malformed or the
/// decoded client order ID is invalid.
pub(crate) fn decode_client_order_id(
encoded: &str,
broker_id: &str,
) -> anyhow::Result<ClientOrderId> {
let decoded = decode_broker_id_checked(encoded, broker_id)?;
ClientOrderId::new_checked(decoded)
.with_context(|| format!("invalid Binance client order ID '{encoded}'"))
}
fn decode_broker_id_checked(encoded: &str, broker_id: &str) -> anyhow::Result<String> {
let prefix = broker_prefix(broker_id);
let Some(payload) = encoded.strip_prefix(&prefix) else {
return Ok(encoded.to_string());
};
let Some((&signal, data)) = payload.as_bytes().split_first() else {
anyhow::bail!("missing broker client order ID signal");
};
match signal {
SIGNAL_O_HYPHENS | SIGNAL_O_NO_HYPHENS => {
anyhow::ensure!(
data.len() == O_FORMAT_B62_LEN,
"invalid O-format broker client order ID payload length"
);
let packed = decode_base62(data).context("invalid O-format broker client order ID")?;
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))View on GitHub (pinned to 18893faf8b)