nautechsystems/nautilus_trader · error
{field} must be in format 'module.path:ClassName'
Error message
{field} must be in format 'module.path:ClassName' What it means
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.
Source
Thrown at crates/system/src/python/registration.rs:528
log::info!("Importing strategy from module: {module_name} class: {class_name}");
Python::attach(|py| -> anyhow::Result<Py<PyAny>> {
let strategy_class = import_python_class(py, module_name, class_name)?;
let config_instance = create_config_instance(py, &config.config_path, &config.config)?;
let python_strategy = if let Some(config_obj) = config_instance.as_ref() {
strategy_class.call1((config_obj,))?
} else {
strategy_class.call0()?
};
Ok(python_strategy.unbind())
})
}
fn split_import_path<'a>(path: &'a str, field: &str) -> anyhow::Result<(&'a str, &'a str)> {
let Some((module_name, class_name)) = path.split_once(':') else {
anyhow::bail!("{field} must be in format 'module.path:ClassName'");
};
if module_name.is_empty() || class_name.is_empty() || class_name.contains(':') {
anyhow::bail!("{field} must be in format 'module.path:ClassName'");
}
Ok((module_name, class_name))
}
fn import_python_class<'py>(
py: Python<'py>,
module_name: &str,
class_name: &str,
) -> anyhow::Result<Bound<'py, PyAny>> {
let module = py
.import(module_name)
.map_err(|e| anyhow::anyhow!("Failed to import module {module_name}: {e}"))?;
View on GitHub (pinned to 18893faf8b)
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
Example fix
// before controller_path = "nautilus_trader.examples.controllers.MyController" // after controller_path = "nautilus_trader.examples.controllers:MyController"
Defensive patterns
Strategy: validation
Validate before calling
import re assert re.fullmatch(r"[\w.]+:[\w.]+", controller_path), "need 'module.path:ClassName'"
Type guard
def is_valid_import_path(path: str) -> bool:
if ":" not in path:
return False
mod, cls = path.split(":", 1)
return bool(mod) and bool(cls) and ":" not in cls Try / catch
try:
trader.add_controller_from_importable_config(cfg)
except ValueError as e:
if "must be in format" in str(e):
raise ConfigError(f"bad import path: {cfg.controller_path}") from e
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- config_path must be in format 'module.path:ClassName', was {
- config_path must be in format 'module.path:ClassName', was {
- Failed to set attribute {key}: {setattr_err}
- Failed to create config instance. Tried kwargs: {kwargs_err}
- Failed to set attribute {key}: {setattr_err}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8a7bbb429ac3ead7.
Report an issue: GitHub.