nautechsystems/nautilus_trader · error · anyhow::Error

filter_callable {filter_callable} failed: {e}

Error message

filter_callable {filter_callable} failed: {e}

What it means

Guard in passes_filter_callable: invoking the configured Python filter callable raised an exception; the module.callable path and the Python error are embedded in the message so instrument filtering can be diagnosed.

Source

Thrown at crates/adapters/interactive_brokers/src/providers/instruments.rs:1798

            use pyo3::{prelude::*, types::PyModule};

            Python::attach(|py| {
                let (module_name, callable_name) =
                    filter_callable.rsplit_once('.').ok_or_else(|| {
                        anyhow::anyhow!(
                            "Invalid filter_callable path {filter_callable:?}; expected module.callable"
                        )
                    })?;
                let callable = PyModule::import(py, module_name)
                    .map_err(|e| anyhow::anyhow!("Failed to import {module_name}: {e}"))?
                    .getattr(callable_name)
                    .map_err(|e| anyhow::anyhow!("Failed to resolve {filter_callable}: {e}"))?;
                let py_instrument = instrument_any_to_pyobject(py, instrument.clone())
                    .map_err(|e| anyhow::anyhow!("Failed to convert instrument to Python: {e}"))?;
                callable
                    .call1((py_instrument,))
                    .and_then(|result| result.extract::<bool>())
                    .map_err(|e| anyhow::anyhow!("filter_callable {filter_callable} failed: {e}"))
            })
        }

        #[cfg(not(feature = "python"))]
        {
            let _ = instrument;
            anyhow::bail!(
                "filter_callable {filter_callable:?} requires the Interactive Brokers adapter to be built with the python feature"
            );
        }
    }

    /// Batch load multiple instrument IDs.
    ///
    /// This method fetches and caches contract details for multiple instrument IDs in parallel.
    ///
    /// # Arguments
    ///

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Make the filter return a plain Python bool for every instrument, guarding missing attributes with getattr(..., default)
  2. Wrap the filter body in try/except and return False for instruments it cannot handle
  3. Confirm the filter signature is (instrument) -> bool with no extra required args
  4. Check the wrapped {e} message to see the original Python traceback/exception

Example fix

# before
def skip_fx(instrument):
    return instrument.price_increment.as_decimal() < 1
# after
def skip_fx(instrument):
    try:
        return bool(instrument.price_increment.as_decimal() < 1)
    except Exception:
        return False
Defensive patterns

Strategy: try-catch

Validate before calling

def _safe_filter(fn):
    def wrapped(inst):
        try:
            return bool(fn(inst))
        except Exception:
            return False
    return wrapped

Type guard

def is_bool_filter(fn) -> bool:
    return callable(fn) and getattr(fn, '__annotations__', {}).get('return') is bool

Try / catch

try:
    result = process_contract_detail(details, filter_callable)
except Exception as e:
    if "filter_callable" in str(e) and "failed" in str(e):
        logging.warning("filter raised; check its assumptions: %s", e)
    else:
        raise

Prevention

When it happens

Trigger: The user filter function raises (e.g. KeyError on an instrument property it assumes exists, division by zero) or returns something non-bool (None, a numpy bool wrapper that fails extract, a string) instead of a Python bool.

Common situations: Filter written assuming attributes that some instruments lack (e.g. .strike_price on a futures contract); filter returning a numpy.bool_ or Optional that pyo3 cannot extract into bool; filter performing network/IO and raising.

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


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