nautechsystems/nautilus_trader · error
provider order price {} does not match cached order price {c
Error message
provider order price {} does not match cached order price {cached_price} What it means
During Polymarket order reconciliation, the adapter validates that an open order returned by the provider matches the locally cached Nautilus order row before emitting an order status report. This error means the price on the provider's open order differs from the price of the cached Limit order, so the adapter cannot safely correlate the venue row with the client order. It is thrown because reconciling against a mismatched row would produce incorrect fill/order state.
Source
Thrown at crates/adapters/polymarket/src/execution/reconciliation.rs:503
provider_expire_time: Option<UnixNanos>,
) -> anyhow::Result<()> {
anyhow::ensure!(
cached_order.order_side() == provider_order.side.into(),
"provider order side {} does not match cached order side {}",
provider_order.side,
cached_order.order_side(),
);
anyhow::ensure!(
cached_order.time_in_force() == provider_order.order_type.into(),
"provider order time in force {} does not match cached order time in force {}",
provider_order.order_type,
cached_order.time_in_force(),
);
validate_client_bound_order_quantity(provider_order, expected_quantity)?;
let cached_price = cached_order
.price()
.context("cached Limit order is missing price")?;
anyhow::ensure!(
cached_price.as_decimal() == provider_order.price,
"provider order price {} does not match cached order price {cached_price}",
provider_order.price,
);
let provider_expire_seconds = provider_expire_time.map(|value| value.as_seconds());
let cached_expire_seconds = cached_order
.expire_time()
.filter(|value| !value.is_zero())
.map(|value| value.as_seconds());
if cached_order.time_in_force() == TimeInForce::Gtd {
anyhow::ensure!(
cached_expire_seconds == provider_expire_seconds,
"provider order expiration seconds {provider_expire_seconds:?} do not match cached order expiration seconds {cached_expire_seconds:?}",
);
}
Ok(())View on GitHub (pinned to 18893faf8b)
Solutions
- Compare the cached order's price with the venue's reported price for that order id; update or clear the stale cache entry so it reflects the current venue price.
- Ensure price_precision on the instrument matches when the order was placed, and that the price passed to submit_order was not rounded differently (use instrument.make_price).
- Reconcile from scratch (drop the cached row and let the adapter import the venue order unbound), then rebind the client order id.
- If the order was legitimately amended, cancel and replace rather than editing cached state manually.
Example fix
// before: cache built from stale snapshot
let cached = cache.order(&client_order_id)?; // price 0.55
// after: refresh/validate cache against venue before reconciliation
let report = client.get_order(&venue_order_id).await?;
if cached.price().as_decimal() != report.price {
// cancel stale row / re-import venue order instead of asserting
log::warn!("cache drift for {venue_order_id}; re-importing venue state");
} Defensive patterns
Strategy: validation
Validate before calling
if let Some(cached) = cache.order_for_venue(&venue_order_id) {
let venue = client.get_order(&venue_order_id).await?;
if cached.price().as_decimal() != venue.price {
return Err(anyhow!("cache/venue price drift for {venue_order_id}: {} vs {}", cached.price(), venue.price));
}
} Type guard
fn prices_match(cached: &OrderAny, provider_price: Decimal) -> bool {
cached.price().map(|p| p.as_decimal() == provider_price).unwrap_or(false)
} Try / catch
match result {
Err(e) if e.to_string().contains("does not match cached order price") => {
log::warn!("stale cached order price; re-importing venue state");
reconcile_unbound(&venue_order_id).await?;
}
other => other?,
} Prevention
- Always construct order prices with instrument.make_price so precision matches the venue.
- Never hand-edit cached order state; let the adapter update it from execution events.
- After a restart, re-sync open orders from the venue before reconciling against the cache.
When it happens
Trigger: Calling order reconciliation (e.g. generate_order_status_reports / build_order_report_from_order) for a target order with a cached Limit order whose `price()` differs from `PolymarketOpenOrder.price` for the same venue order id. Happens when the cache holds a stale or wrong row for that venue_order_id, or when price fields from the venue come back in a different precision/representation so `cached_price.as_decimal() != provider_order.price`.
Common situations: Stale cache after the order was amended/repriced but the cached price was not updated; restoring state from an old cache file while venue orders moved; restart with a different price precision/rounding config than when the order was placed; fetching reports for a venue order id that was reused or remapped to a different client order.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- provider venue order {} does not match requested venue order
- unmapped_in_scope_message("open order", instrument_id, Some(
- unmapped_in_scope_message("position", instrument_id, None, c
- expected Polymarket BinaryOption instrument, found {instrume
- provider venue order {} is not owned by the account
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/26ce9e6e9db17fa4.
Report an issue: GitHub.