nautechsystems/nautilus_trader · error
Fill missing both trd_match_id and exec_id
Error message
Fill missing both trd_match_id and exec_id
What it means
parse_fill_report builds a TradeId from `trd_match_id`, falling back to `exec_id`. This error fires only when BOTH fields are absent, meaning the fill cannot be uniquely identified. The parser fails so the record is not silently mis-attributed.
Source
Thrown at crates/adapters/bitmex/src/http/parse.rs:1104
// Skip non-trade executions (funding, settlements, etc.)
// Trade executions have exec_type of Trade and must have order_id
if !matches!(exec.exec_type, BitmexExecType::Trade) {
anyhow::bail!("Skipping non-trade execution: {:?}", exec.exec_type);
}
// Additional check: skip executions without order_id (likely funding/settlement)
let order_id = exec.order_id.ok_or_else(|| {
anyhow::anyhow!("Skipping execution without order_id: {:?}", exec.exec_type)
})?;
let account_id = bitmex_account_id(exec.account);
let instrument_id = instrument.id();
let venue_order_id = VenueOrderId::new(order_id.to_string());
// trd_match_id might be missing for some execution types, use exec_id as fallback
let trade_id = TradeId::new(
exec.trd_match_id
.or(Some(exec.exec_id))
.ok_or_else(|| anyhow::anyhow!("Fill missing both trd_match_id and exec_id"))?
.to_string(),
);
// Skip executions without side (likely not trades)
let Some(side) = exec.side else {
anyhow::bail!("Skipping execution without side: {:?}", exec.exec_type);
};
let order_side = OrderSide::from(side);
let last_qty = parse_signed_contracts_quantity(exec.last_qty, instrument);
let last_px = Price::new(exec.last_px, instrument.price_precision());
// Map BitMEX currency to standard currency code
let settlement_currency_str = exec.settl_currency.unwrap_or(Ustr::from("XBT")).as_str();
let mapped_currency = map_bitmex_currency(settlement_currency_str);
let currency = get_currency(&mapped_currency);
let commission = Money::new(exec.commission.unwrap_or(0.0), currency);
let liquidity_side = parse_liquidity_side(&exec.last_liquidity_ind);
let client_order_id = exec.cl_ord_id.map(ClientOrderId::new);
let venue_position_id = None; // Not applicable on BitMEXView on GitHub (pinned to 18893faf8b)
Solutions
- Catch and skip the record in the caller, logging the raw execution for diagnosis.
- Verify the BitMEX API response shape for the affected executions (dump raw JSON).
- Update the adapter if BitMEX changed field naming/optionality.
- Filter executions to those with an exec_id before parsing.
Example fix
// before
let trade_id = TradeId::new(exec.trd_match_id.or(Some(exec.exec_id)).ok_or_else(|| anyhow::anyhow!("Fill missing both trd_match_id and exec_id"))?.to_string());
// after
let Some(id_src) = exec.trd_match_id.or(Some(exec.exec_id)) else {
log::warn!("Skipping fill without trd_match_id/exec_id");
return Ok(None);
};
let trade_id = TradeId::new(id_src.to_string()); Defensive patterns
Strategy: type-guard
Validate before calling
if exec.trd_match_id.is_none() && exec.exec_id.is_empty() { /* skip record */ } Type guard
fn has_trade_id(exec: &BitmexExecution) -> bool {
exec.trd_match_id.is_some() || !exec.exec_id.is_empty()
} Try / catch
let Ok(report) = parse_fill_report(exec, instrument) else {
log::debug!("fill without trade id skipped");
continue;
}; Prevention
- Verify exec_id is always populated in your BitMEX response versions.
- Dump raw execution JSON when this fires to detect API schema drift.
- Skip rather than fail when a fill cannot be uniquely identified.
When it happens
Trigger: request_fill_reports encountering an execution row where both trd_match_id and exec_id are null — malformed or highly unusual BitMEX execution payloads.
Common situations: Unusual execution types in fill history (transfers, adjustments); BitMEX API schema drift where a previously-guaranteed field becomes optional; corrupted/partial REST responses.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Skipping non-trade execution: {:?}
- Skipping execution without side: {:?}
- Trade bin missing high price for {instrument_id}
- Trade bin missing low price for {instrument_id}
- Trade bin missing close price for {instrument_id}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/1958953e6aab7403.
Report an issue: GitHub.