nautechsystems/nautilus_trader · error · anyhow::Error

unmapped_in_scope_message("position", instrument_id, None, c

Error message

unmapped_in_scope_message("position", instrument_id, None, collection_load_ids,)

What it means

During Polymarket position reconciliation, a non-dust position's asset maps to an instrument_id that was not loaded by the instrument provider. Like the open-order variant, this uses unmapped_in_scope_message and aborts reconciliation because an in-scope position cannot be reported without its instrument definition.

Source

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

    let instrument_id = instrument_id_from_market_token(&position.condition_id, &position.asset);

    if instrument_filter
        .is_some_and(|filter_id| !polymarket_instrument_ids_equivalent(filter_id, instrument_id))
    {
        return Ok(None);
    }

    if !instrument_in_load_ids_scope(instrument_id, collection_load_ids) {
        log::debug!("Dropping out-of-scope position instrument {instrument_id}");
        return Ok(None);
    }

    if position_is_dust(position) {
        return Ok(None);
    }

    if !position_instrument_loaded(&position.asset, instrument_id, instruments) {
        anyhow::bail!(unmapped_in_scope_message(
            "position",
            instrument_id,
            None,
            collection_load_ids,
        ));
    }

    Ok(build_position_report_from_reportable_position(
        position, account_id, ts,
    ))
}

/// Full reconciliation mass status generation.
#[expect(clippy::too_many_arguments)]
pub(crate) async fn generate_mass_status(
    http_client: &PolymarketClobHttpClient,
    data_api_client: &PolymarketDataApiHttpClient,
    instruments: &AtomicMap<Ustr, InstrumentAny>,

View on GitHub (pinned to d1527c24af)

Solutions

  1. Widen the instrument provider load scope (or remove filters) to cover every market with an open position
  2. Verify instruments finished loading before position reconciliation runs
  3. Close stray positions on markets intentionally outside scope, or add those markets to the load list
Defensive patterns

Strategy: validation

Validate before calling

let instruments: HashSet<InstrumentId> = cache.instrument_ids().into_iter().collect();
// before position reconciliation: every market with a non-dust position must be loaded
for pos in provider_positions {
    if !instruments.contains(&map_asset_to_instrument(&pos.asset)?) {
        log::warn!("position on unloaded market {}", pos.asset);
    }
}

Prevention

When it happens

Trigger: Position report generation where position_instrument_loaded returns false for a position's asset — the provider returned positions for markets whose definitions are missing from the local cache.

Common situations: Instrument load filters narrower than the account's actual positions; failed instrument fetches at startup; positions on newly created markets not present in the cached snapshot.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@d1527c24af (2026-08-27). Data as JSON: /api/errors/bca71dbb5aa9f1f9. Report an issue: GitHub.