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
- Make the filter return a plain Python bool for every instrument, guarding missing attributes with getattr(..., default)
- Wrap the filter body in try/except and return False for instruments it cannot handle
- Confirm the filter signature is (instrument) -> bool with no extra required args
- 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
- Wrap filter bodies in try/except returning False for unsupported instruments
- Always return a plain Python bool (bool(...) around numpy values)
- Test filters against all instrument kinds they will receive
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
- Python SimulationModule.pre_process failed: {e}
- Python SimulationModule.process failed: {e}
- Python SimulationModule.acknowledge failed: {e}
- Python on_order failed: {e}
- Python on_order_list failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/60869b3881d17ccc.
Report an issue: GitHub.