{"record":{"id":"60869b3881d17ccc","repo":"nautechsystems/nautilus_trader","slug":"filter-callable-filter-callable-failed-e","errorCode":null,"errorMessage":"filter_callable {filter_callable} failed: {e}","messagePattern":"filter_callable (.+?) failed: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/providers/instruments.rs","lineNumber":1798,"sourceCode":"            use pyo3::{prelude::*, types::PyModule};\n\n            Python::attach(|py| {\n                let (module_name, callable_name) =\n                    filter_callable.rsplit_once('.').ok_or_else(|| {\n                        anyhow::anyhow!(\n                            \"Invalid filter_callable path {filter_callable:?}; expected module.callable\"\n                        )\n                    })?;\n                let callable = PyModule::import(py, module_name)\n                    .map_err(|e| anyhow::anyhow!(\"Failed to import {module_name}: {e}\"))?\n                    .getattr(callable_name)\n                    .map_err(|e| anyhow::anyhow!(\"Failed to resolve {filter_callable}: {e}\"))?;\n                let py_instrument = instrument_any_to_pyobject(py, instrument.clone())\n                    .map_err(|e| anyhow::anyhow!(\"Failed to convert instrument to Python: {e}\"))?;\n                callable\n                    .call1((py_instrument,))\n                    .and_then(|result| result.extract::<bool>())\n                    .map_err(|e| anyhow::anyhow!(\"filter_callable {filter_callable} failed: {e}\"))\n            })\n        }\n\n        #[cfg(not(feature = \"python\"))]\n        {\n            let _ = instrument;\n            anyhow::bail!(\n                \"filter_callable {filter_callable:?} requires the Interactive Brokers adapter to be built with the python feature\"\n            );\n        }\n    }\n\n    /// Batch load multiple instrument IDs.\n    ///\n    /// This method fetches and caches contract details for multiple instrument IDs in parallel.\n    ///\n    /// # Arguments\n    ///","sourceCodeStart":1780,"sourceCodeEnd":1816,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/providers/instruments.rs#L1780-L1816","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\ndef skip_fx(instrument):\n    return instrument.price_increment.as_decimal() < 1\n# after\ndef skip_fx(instrument):\n    try:\n        return bool(instrument.price_increment.as_decimal() < 1)\n    except Exception:\n        return False","handlingStrategy":"try-catch","validationCode":"def _safe_filter(fn):\n    def wrapped(inst):\n        try:\n            return bool(fn(inst))\n        except Exception:\n            return False\n    return wrapped","typeGuard":"def is_bool_filter(fn) -> bool:\n    return callable(fn) and getattr(fn, '__annotations__', {}).get('return') is bool","tryCatchPattern":"try:\n    result = process_contract_detail(details, filter_callable)\nexcept Exception as e:\n    if \"filter_callable\" in str(e) and \"failed\" in str(e):\n        logging.warning(\"filter raised; check its assumptions: %s\", e)\n    else:\n        raise","preventionTips":["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"],"tags":["python","callback","filter","exception"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}