{"record":{"id":"a487fd35e92fbd53","repo":"nautechsystems/nautilus_trader","slug":"failed-to-get-class-class-name-e-a487fd","errorCode":null,"errorMessage":"Failed to get class {class_name}: {e}","messagePattern":"Failed to get class (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/python/node.rs","lineNumber":484,"sourceCode":"            \"{path_field} must be in format 'module.path:ClassName'\",\n        )));\n    };\n\n    if module_name.is_empty() || class_name.is_empty() || class_name.contains(':') {\n        return Err(to_pyvalue_err(format!(\n            \"{path_field} must be in format 'module.path:ClassName'\",\n        )));\n    }\n\n    log::info!(\"Importing {component_name} from module: {module_name} class: {class_name}\");\n\n    Python::attach(|py| -> anyhow::Result<Py<PyAny>> {\n        let module = py\n            .import(module_name)\n            .map_err(|e| anyhow::anyhow!(\"Failed to import module {module_name}: {e}\"))?;\n        let class = module\n            .getattr(class_name)\n            .map_err(|e| anyhow::anyhow!(\"Failed to get class {class_name}: {e}\"))?;\n        let config_instance = create_config_instance(py, config_path, config)?;\n        let component = if let Some(config_obj) = config_instance {\n            class.call1((config_obj,))?\n        } else {\n            class.call0()?\n        };\n        Ok(component.unbind())\n    })\n    .map_err(to_pyruntime_err)\n}\n\npub(crate) fn create_config_instance<'py>(\n    py: Python<'py>,\n    config_path: &str,\n    config: &HashMap<String, serde_json::Value>,\n) -> anyhow::Result<Option<Bound<'py, PyAny>>> {\n    if config_path.is_empty() && config.is_empty() {\n        log::debug!(\"No config_path or empty config, using None\");","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/python/node.rs#L466-L502","documentation":"After successfully importing the module, create_importable_component fetches the component class with module.getattr(class_name). This error means the attribute (class name) does not exist on the imported module — or importing it as an attribute raised — so the actor/strategy/exec algorithm cannot be constructed.","triggerScenarios":"py_add_actor_from_config / py_add_strategy_from_config / py_add_exec_algorithm_from_config with a config whose class name is misspelled, is not defined at module top level, or was renamed in a newer version of the user's code.","commonSituations":"Renaming the strategy class but not the config; class defined inside a function or submodule (e.g. strategies.my_strategy.MyStrategy vs strategies.MyStrategy); typos in casing ('myStrategy' vs 'MyStrategy').","solutions":["Check the class name string in the config matches the top-level class exactly (case-sensitive).","Confirm the class is defined at module scope, not nested in a function or another module.","Run `python -c \"from <module> import <class>\"` to reproduce the exact getattr failure.","Update stale configs after refactors/renames of the strategy or actor class."],"exampleFix":"# before\nconfig = MyStrategyConfig(module=\"strategies.my_strategy\", class_name=\"MyStrat\")  # renamed\n# after\nconfig = MyStrategyConfig(module=\"strategies.my_strategy\", class_name=\"MyStrategy\")","handlingStrategy":"validation","validationCode":"import importlib\ndef assert_class_exists(module_name: str, class_name: str):\n    mod = importlib.import_module(module_name)\n    assert hasattr(mod, class_name), f\"{module_name} has no attribute {class_name}\"\nassert_class_exists(config.module, config.class_name)\n","typeGuard":null,"tryCatchPattern":"try:\n    node.add_strategy_from_config(strategy_config)\nexcept Exception as e:\n    if \"Failed to get class\" in str(e):\n        raise SystemExit(f\"Class name mismatch in config: {e}\") from e\n    raise\n","preventionTips":["Keep class names in configs generated from the classes themselves (avoid hand-typed strings).","Grep configs after refactors/renames of strategy or actor classes.","Respect Python casing: class names are case-sensitive in getattr."],"tags":["python","import","backtest","config"],"backgroundTag":"class-not-found","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"}