{"record":{"id":"8a7bbb429ac3ead7","repo":"nautechsystems/nautilus_trader","slug":"field-must-be-in-format-module-path-classname","errorCode":null,"errorMessage":"{field} must be in format 'module.path:ClassName'","messagePattern":"(.+?) must be in format 'module\\.path:ClassName'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/system/src/python/registration.rs","lineNumber":528,"sourceCode":"    log::info!(\"Importing strategy from module: {module_name} class: {class_name}\");\n\n    Python::attach(|py| -> anyhow::Result<Py<PyAny>> {\n        let strategy_class = import_python_class(py, module_name, class_name)?;\n        let config_instance = create_config_instance(py, &config.config_path, &config.config)?;\n\n        let python_strategy = if let Some(config_obj) = config_instance.as_ref() {\n            strategy_class.call1((config_obj,))?\n        } else {\n            strategy_class.call0()?\n        };\n\n        Ok(python_strategy.unbind())\n    })\n}\n\nfn split_import_path<'a>(path: &'a str, field: &str) -> anyhow::Result<(&'a str, &'a str)> {\n    let Some((module_name, class_name)) = path.split_once(':') else {\n        anyhow::bail!(\"{field} must be in format 'module.path:ClassName'\");\n    };\n\n    if module_name.is_empty() || class_name.is_empty() || class_name.contains(':') {\n        anyhow::bail!(\"{field} must be in format 'module.path:ClassName'\");\n    }\n\n    Ok((module_name, class_name))\n}\n\nfn import_python_class<'py>(\n    py: Python<'py>,\n    module_name: &str,\n    class_name: &str,\n) -> anyhow::Result<Bound<'py, PyAny>> {\n    let module = py\n        .import(module_name)\n        .map_err(|e| anyhow::anyhow!(\"Failed to import module {module_name}: {e}\"))?;\n","sourceCodeStart":510,"sourceCodeEnd":546,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/system/src/python/registration.rs#L510-L546","documentation":"Thrown by `split_import_path` when an importable path string is missing the required `module.path:ClassName` separator. The library resolves actors and strategies from Python import paths and needs exactly one `:` separating the dotted module from the class name. The error names the offending field (e.g. 'controller_path' or 'strategy_path') so you know which config value is malformed.","triggerScenarios":"Passing `module.path.ClassName` (dots only, no colon), `module.path:` (empty class), `:ClassName` (empty module), `a:b:c` (colon inside class name), or a plain class name to create_python_actor / create_python_strategy via the config path field.","commonSituations":"Copying a Python dotted path (`nautilus_trader.examples.strategies.ema_cross.EMACross`) into an import path field without appending `:EMACross`; typos with double colons; Windows-style path strings accidentally containing colons.","solutions":["Format the path as `module.path:ClassName`, e.g. `my_pkg.strategies:MyStrategy`","Verify the class name after the colon is non-empty and contains no further colons","Check your config file for the field named in the error message and correct its value","Test the import manually with `importlib.import_module('module.path')` and `getattr` to confirm the class exists"],"exampleFix":"// before\ncontroller_path = \"nautilus_trader.examples.controllers.MyController\"\n// after\ncontroller_path = \"nautilus_trader.examples.controllers:MyController\"","handlingStrategy":"validation","validationCode":"import re\nassert re.fullmatch(r\"[\\w.]+:[\\w.]+\", controller_path), \"need 'module.path:ClassName'\"","typeGuard":"def is_valid_import_path(path: str) -> bool:\n    if \":\" not in path:\n        return False\n    mod, cls = path.split(\":\", 1)\n    return bool(mod) and bool(cls) and \":\" not in cls","tryCatchPattern":"try:\n    trader.add_controller_from_importable_config(cfg)\nexcept ValueError as e:\n    if \"must be in format\" in str(e):\n        raise ConfigError(f\"bad import path: {cfg.controller_path}\") from e\n    raise","preventionTips":["Store import paths (with colon) separately from dotted Python paths in configs","Add a config-schema validation step at startup","Copy-paste import paths from working examples rather than retyping them"],"tags":["rust","python","config","format"],"backgroundTag":"invalid-argument-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}