nautechsystems/nautilus_trader · critical
provider outcome {outcome} does not match instrument outcome
Error message
provider outcome {outcome} does not match instrument outcome {instrument_outcome} What it means
As part of binding a provider order/trade to the local instrument, the binary outcome (e.g. YES/NO) from the provider must exactly equal the instrument's outcome metadata. This error fires when the provider object's outcome differs from the instrument's configured outcome, so the fill would be attributed to the wrong side of the binary market.
Source
Thrown at crates/adapters/polymarket/src/execution/reconciliation.rs:259
outcome: PolymarketOutcome,
) -> anyhow::Result<()> {
let InstrumentAny::BinaryOption(binary) = instrument else {
anyhow::bail!("expected Polymarket BinaryOption instrument, found {instrument:?}");
};
let instrument_condition = binary
.info
.as_ref()
.and_then(|info| info.get_str("condition_id"))
.context("Polymarket instrument is missing condition_id metadata")?;
anyhow::ensure!(
instrument_condition.eq_ignore_ascii_case(condition_id),
"provider condition {condition_id} does not match instrument condition {instrument_condition}",
);
let instrument_outcome = binary
.outcome
.context("Polymarket instrument is missing outcome metadata")?;
anyhow::ensure!(
instrument_outcome == outcome.as_str(),
"provider outcome {outcome} does not match instrument outcome {instrument_outcome}",
);
Ok(())
}
fn validate_quantity_evidence(
value: Decimal,
precision: u8,
field: &str,
allow_zero: bool,
) -> anyhow::Result<()> {
if allow_zero {
anyhow::ensure!(
value >= Decimal::ZERO,
"{field} {value} must be non-negative"
);View on GitHub (pinned to 18893faf8b)
Solutions
- Compare the token_id of the order/fill with the token_id configured for the instrument's outcome; ensure the right token is subscribed.
- Fix the instrument configuration so binary.outcome matches the token actually being traded.
- Normalize outcome strings if the provider changed casing or naming.
- Refetch market metadata and rebuild the instrument if the market definition changed.
Example fix
// before
let instrument = instrument_for_token(order.asset_id)?;
validate_instrument_binding(&order, &instrument)?;
// after: guard outcome before validation
let instrument = instrument_for_token(order.asset_id)?;
if instrument.outcome.as_str() != order.outcome.as_str() {
anyhow::bail!("token {} maps to outcome {}, not {}", order.asset_id, instrument.outcome, order.outcome);
}
validate_instrument_binding(&order, &instrument)?; Defensive patterns
Strategy: validation
Validate before calling
fn outcome_matches(instrument: &Instrument, outcome: &str) -> bool {
instrument.outcome.as_str() == outcome
} Type guard
fn instrument_for_outcome<'a>(instruments: &'a [Instrument], condition: &str, outcome: &str) -> Option<&'a Instrument> {
instruments.iter().find(|i| i.condition_id().eq_ignore_ascii_case(condition) && i.outcome.as_str() == outcome)
} Try / catch
match validate_instrument_binding(&fill, &instrument) {
Ok(()) => (),
Err(e) if e.to_string().contains("outcome") => warn!("fill for opposite outcome token; skipping"),
Err(e) => return Err(e),
} Prevention
- Key instrument lookup by token_id, not just condition_id (both outcomes share a condition)
- Verify the subscribed token_id maps to the intended outcome before trading
- Normalize outcome strings against the provider's exact naming
When it happens
Trigger: validate_instrument_binding (from build_order_report_from_order, classify_target_trade, build_fill_reports_from_trades) receives a provider object whose outcome string differs from binary.outcome, after the condition_id check passed (condition matched but outcome flipped).
Common situations: Trading the opposite token of the same market (YES vs NO) with an instrument configured for the other outcome; both outcomes share a condition_id so only this check catches it; outcome naming/casing differences from provider updates.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- provider condition {condition_id} does not match instrument
- Polymarket execution shutdown failed: {}
- Polymarket CLOB protocol version {version} is unsupported; a
- provider venue order {} is not owned by the account
- unmapped in-scope open order instrument {instrument_id} (tok
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0a5e32a36cd74597.
Report an issue: GitHub.