nautechsystems/nautilus_trader · error
trade {} trader_side {:?} contradicts target order {venue_or
Error message
trade {} trader_side {:?} contradicts target order {venue_order_id} participant role What it means
After determining the target order's role in the trade (maker or taker), the code cross-checks the trade's declared trader_side field. This error fires when the declared side (Maker/Taker) contradicts the order's actual participant role in the trade — the provider data is internally inconsistent.
Source
Thrown at crates/adapters/polymarket/src/execution/reconciliation.rs:171
venue_order_id: VenueOrderId,
) -> anyhow::Result<bool> {
let target_is_taker = trade.taker_order_id == venue_order_id.as_str();
let target_maker_occurrences = trade
.maker_orders
.iter()
.filter(|order| order.order_id == venue_order_id.as_str())
.count();
let target_is_maker = target_maker_occurrences > 0;
if !target_is_taker && !target_is_maker {
return Ok(false);
}
anyhow::ensure!(
usize::from(target_is_taker) + target_maker_occurrences == 1,
"target order {venue_order_id} appears more than once in trade {}",
trade.id,
);
let declared_maker = trade.trader_side == PolymarketLiquiditySide::Maker;
anyhow::ensure!(
declared_maker == target_is_maker,
"trade {} trader_side {:?} contradicts target order {venue_order_id} participant role",
trade.id,
trade.trader_side,
);
Ok(true)
}
fn validate_maker_order_side(
trade: &PolymarketTradeReport,
maker_order: &PolymarketMakerOrder,
) -> anyhow::Result<OrderSide> {
let derived_side = determine_order_side(
trade.trader_side,
trade.side,
trade.asset_id.as_str(),
maker_order.asset_id.as_str(),
);View on GitHub (pinned to 18893faf8b)
Solutions
- Log the trade payload and compare trade.trader_side against the order's position in maker_orders vs taker fields.
- Re-fetch the trade from the provider API to rule out a stale or mid-update record.
- Check for recent Polymarket API schema changes affecting trader_side semantics and update parsing.
- Drop the inconsistent trade from reconciliation and surface it for manual review.
Example fix
// before
anyhow::ensure!(declared_maker == target_is_maker, ...);
// after: detect and skip contradictory trades upstream
if (trade.trader_side == PolymarketLiquiditySide::Maker) != target_is_maker {
warn!("trade {} has contradictory trader_side; skipping", trade.id);
return Ok(false);
} Defensive patterns
Strategy: validation
Validate before calling
fn trader_side_consistent(trade: &Trade, vid: &str) -> bool {
let is_maker = trade.maker_orders.iter().any(|o| o.order_id == vid);
(trade.trader_side == PolymarketLiquiditySide::Maker) == is_maker
} Type guard
fn declared_side_matches_role(trade: &Trade, vid: &str) -> bool {
let role_is_maker = trade.maker_orders.iter().any(|o| o.order_id == vid);
match trade.trader_side {
PolymarketLiquiditySide::Maker => role_is_maker,
PolymarketLiquiditySide::Taker => !role_is_maker,
}
} Try / catch
match classify_target_trade(&trade, &venue_order_id) {
Ok(is_target) => { /* proceed */ }
Err(e) if e.to_string().contains("contradicts") => warn!("inconsistent trade skipped: {e}"),
Err(e) => return Err(e),
} Prevention
- Validate trader_side against the role list immediately after parsing provider trades
- Re-fetch trades that look inconsistent before discarding them
- Track Polymarket API changelog for trader_side semantics changes
When it happens
Trigger: classify_target_trade -> validate_target_trade_role sees target_is_maker true while trade.trader_side is not Maker (or vice versa), e.g. trade.trader_side == Taker but the venue order id only appears in the maker list.
Common situations: Provider data-api returning inconsistent trader_side after a trade format change; a trade where the authenticated trader fields are mismatched to the order list; cached/stale trade objects merged incorrectly.
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
- target order {venue_order_id} appears more than once in trad
- provider venue order {} is not owned by the account
- unmapped in-scope open order instrument {instrument_id} (tok
- unmapped in-scope position instrument {instrument_id}; {hint
- conflicting RTDS TWAP observation topic={} symbol={} timesta
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/9b5dbe1df536d309.
Report an issue: GitHub.