nautechsystems/nautilus_trader · error

Failed to convert InstrumentAny to Python: {e}

Error message

Failed to convert InstrumentAny to Python: {e}

What it means

This error is raised in `on_instrument` when converting a Rust `InstrumentAny` domain object into a Python object fails before the Python handler is even called. The conversion (`instrument_any_to_pyobject`) could not produce a valid PyO3-backed Python instrument, so the dispatch never happens.

Source

Thrown at crates/common/src/python/actor.rs:1095

    fn on_signal(&mut self, signal: &Signal) -> anyhow::Result<()> {
        self.dispatch_on_signal(signal)
            .map_err(|e| anyhow::anyhow!("Python on_signal failed: {e}"))
    }

    fn on_queue_state(&mut self, event: &QueueStateChanged) -> anyhow::Result<()> {
        self.dispatch_on_queue_state(event)
            .map_err(|e| anyhow::anyhow!("Python on_queue_state failed: {e}"))
    }

    fn on_socket_state(&mut self, event: &SocketStateChanged) -> anyhow::Result<()> {
        self.dispatch_on_socket_state(event)
            .map_err(|e| anyhow::anyhow!("Python on_socket_state failed: {e}"))
    }

    fn on_instrument(&mut self, instrument: &InstrumentAny) -> anyhow::Result<()> {
        Python::attach(|py| {
            let py_instrument = instrument_any_to_pyobject(py, instrument.clone())
                .map_err(|e| anyhow::anyhow!("Failed to convert InstrumentAny to Python: {e}"))?;
            self.dispatch_on_instrument(py_instrument)
                .map_err(|e| anyhow::anyhow!("Python on_instrument failed: {e}"))
        })
    }

    fn on_quote(&mut self, quote: &QuoteTick) -> anyhow::Result<()> {
        self.dispatch_on_quote(*quote)
            .map_err(|e| anyhow::anyhow!("Python on_quote failed: {e}"))
    }

    fn on_trade(&mut self, tick: &TradeTick) -> anyhow::Result<()> {
        self.dispatch_on_trade(*tick)
            .map_err(|e| anyhow::anyhow!("Python on_trade failed: {e}"))
    }

    fn on_bar(&mut self, bar: &Bar) -> anyhow::Result<()> {
        self.dispatch_on_bar(*bar)
            .map_err(|e| anyhow::anyhow!("Python on_bar failed: {e}"))

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Log the instrument definition received and check which Instrument variant fails conversion
  2. Verify the instrument comes from a supported adapter and passes its own validation (e.g. `InstrumentAny` construction)
  3. Update NautilusTrader and the adapter to matching versions so the variant is supported
  4. Register/subscribe only for instrument types your code supports
Defensive patterns

Strategy: validation

Validate before calling

# validate the instrument before it reaches the actor
def validate_instrument(inst):
    assert inst.id is not None and inst.id.value, 'instrument id missing'
    assert inst.price_increment is not None, 'price_increment missing'
    return inst

Type guard

def is_supported_instrument(instrument) -> bool:
    return type(instrument).__name__ in {
        'CurrencyPair', 'CryptoPerpetual', 'CryptoFuture', 'Equity',
        'FuturesContract', 'OptionsContract', 'Bond', 'Commodity'}

Prevention

When it happens

Trigger: An instrument definition arrives at a Python actor's `on_instrument` and the Rust->Python conversion of the instrument (any of Instrument:: variants) fails, typically due to an unregistered/unsupported instrument type or invalid PyO3 conversion for that variant.

Common situations: Using a custom or newly added instrument type not covered by the conversion, a corrupted/invalid instrument definition received from a data client, or version mismatch between adapter producing the instrument and the core conversion code.

Related errors


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