nautechsystems/nautilus_trader · error

maker order {} appears more than once in trade {}

Error message

maker order {} appears more than once in trade {}

What it means

While rebuilding trades from provider maker-order data, reconciliation asserts that each maker order (by order_id) appears in at most one trade. Seeing the same maker order id in two trades means the provider data is self-contradictory, so the reconciliation fails fast via `anyhow::ensure!` rather than double-counting a fill.

Source

Thrown at crates/adapters/polymarket/src/execution/reconciliation.rs:1171

                    }
                };
                let instrument_id = instrument.id();

                if scope
                    .instrument_id
                    .is_some_and(|requested| instrument_id != requested)
                {
                    continue;
                }

                if !instrument_in_load_ids_scope(instrument_id, load_ids) {
                    log::debug!(
                        "Dropping loaded out-of-scope historical instrument {instrument_id}",
                    );
                    continue;
                }

                anyhow::ensure!(
                    !selected_maker_orders
                        .iter()
                        .any(|(selected, _, _, _)| selected.order_id == mo.order_id),
                    "maker order {} appears more than once in trade {}",
                    mo.order_id,
                    trade.id,
                );

                let identifiers = validate_maker_report_identifiers(trade, mo)?;

                validate_instrument_binding(&instrument, trade.market.as_str(), mo.outcome)?;
                validate_maker_order_side(trade, mo)?;
                let last_px = validate_trade_values(
                    mo.matched_amount,
                    mo.price,
                    instrument.size_precision(),
                    &format!("maker order {} matched amount", mo.order_id),
                    &format!("maker order {} price", mo.order_id),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Log the offending mo.order_id and the two trade ids, then query the Polymarket Data API directly to determine which trade attribution is correct.
  2. Deduplicate maker orders by order_id across all fetched trades before reconciliation, dropping later duplicates whose payloads are identical.
  3. Ensure trade fetches use a consistent snapshot (single request window) so a maker order is not attributed under both a pre- and post-correction record.
  4. Upgrade the nautilus_polymarket adapter if the venue legitimately reattributes maker orders and newer reconciliation logic handles it.

Example fix

// before: hard failure when a maker order spans two trades
anyhow::ensure!(
    !selected_maker_orders.iter().any(|(selected, _, _, _)| selected.order_id == mo.order_id),
    "maker order {} appears more than once in trade {}",
    mo.order_id,
    trade.id,
);
// after: pre-deduplicate maker orders by order_id so each appears once
let mut seen_maker_orders: AHashSet<Uuid> = AHashSet::new();
for mo in maker_orders {
    if !seen_maker_orders.insert(mo.order_id) {
        log::warn!("Skipping duplicate maker order {}", mo.order_id);
        continue;
    }
    // ... admit maker order
}
Defensive patterns

Strategy: validation

Validate before calling

let mut seen: AHashSet<Uuid> = AHashSet::new();
for mo in all_maker_orders() {
    if !seen.insert(mo.order_id) {
        return Err(anyhow::anyhow!(
            "maker order {} pre-attributed to multiple trades; resolve before reconciling",
            mo.order_id,
        ));
    }
}

Type guard

fn is_unique_maker_order(seen: &mut AHashSet<Uuid>, mo: &PolymarketMakerOrder) -> bool {
    seen.insert(mo.order_id)
}

Try / catch

match reconciliation_result {
    Err(e) if e.to_string().contains("appears more than once in trade") => {
        log::warn!("duplicate maker order attribution; re-fetching trades from provider");
        retry_with_fresh_snapshot();
    }
    other => other?,
}

Prevention

When it happens

Trigger: Running Polymarket trade/fill reconciliation (the code path that iterates `selected_maker_orders` for a trade) when the provider response contains the same maker order_id attributed to two distinct trade ids, or duplicated within one trade's maker list.

Common situations: Provider API returning overlapping trade records across paginated queries; venue self-trade or merger of two fills causing one maker order to span records; mixing trades fetched at different times where one was later corrected/merged; buggy local grouping that inserts the same maker order into multiple trade buckets.

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/0150284b3240cfb3. Report an issue: GitHub.