nautechsystems/nautilus_trader · error
Custom data type "{type_name}" is already registered for Pyt
Error message
Custom data type "{type_name}" is already registered for Python extraction What it means
register_py_extractor registers a Python object extractor for a custom data type name in the Python-feature registry. The registry rejects duplicate names with this error so an existing extractor is never silently replaced.
Source
Thrown at crates/model/src/data/registry.rs:271
#[cfg(feature = "python")]
fn py_extractors() -> &'static DashMap<String, PyExtractor> {
static PY_EXTRACTORS: std::sync::OnceLock<DashMap<String, PyExtractor>> =
std::sync::OnceLock::new();
PY_EXTRACTORS.get_or_init(DashMap::new)
}
/// Registers a `PyExtractor` for the given custom data type name.
/// Used by `CustomData` constructor to convert Python objects to `Arc<dyn CustomDataTrait>`.
///
/// # Errors
/// Returns an error if the type is already registered.
#[cfg(feature = "python")]
pub fn register_py_extractor(type_name: &str, extractor: PyExtractor) -> Result<(), anyhow::Error> {
let reg = py_extractors();
match reg.entry(type_name.to_string()) {
Entry::Occupied(_) => {
anyhow::bail!(
"Custom data type \"{type_name}\" is already registered for Python extraction"
);
}
Entry::Vacant(v) => {
v.insert(extractor);
Ok(())
}
}
}
/// Registers a `PyExtractor` for the given custom data type name if not already registered.
/// If the type is already registered, returns `Ok(())` without overwriting (idempotent).
/// Use this where repeated registration can occur (e.g. module init).
///
/// # Errors
/// Does not return an error (idempotent insert into `DashMap`).
#[cfg(feature = "python")]
pub fn ensure_py_extractor_registered(View on GitHub (pinned to 18893faf8b)
Solutions
- Guard registration with a once-only mechanism or an initialized flag in the adapter.
- Catch this error and treat it as a no-op when re-registering the identical extractor.
- Use a unique type name if the collision is between distinct types.
Example fix
// before
def register():
register_py_extractor("MyData", extractor) # fails on reload
// after
_registered = False
def register():
global _registered
if not _registered:
register_py_extractor("MyData", extractor)
_registered = True Defensive patterns
Strategy: try-catch
Validate before calling
# Python
if type_name in getattr(_module, "_py_extractors_registered", set()):
return
_module._py_extractors_registered.add(type_name) Try / catch
# Python
try:
register_py_extractor(type_name, extractor)
except Exception as e:
if "already registered for Python extraction" in str(e):
pass # idempotent re-init
else:
raise Prevention
- Use a module-level registered flag or once-only initialization for Python extraction setup.
- Make registration functions idempotent so notebook re-runs and reloads are safe.
- Keep a single adapter init path that owns all registry registrations.
When it happens
Trigger: Calling register_py_extractor twice for the same type_name — re-imported Python modules, repeated adapter instantiation, or a type registered by both a library crate and user code.
Common situations: Jupyter notebook re-execution re-running registration cells; pytest fixtures instantiating the adapter multiple times; dynamic module reloads.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- No tearsheet chart registered under '{chart_name}'.{hint} Re
- Theme '{name}' not found.{suggestion_text} Available themes:
- Theme name cannot be empty
- Custom data type "{type_name}" is already registered for JSO
- Custom data type "{type_name}" is already registered for Arr
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/93a981b3b1d62dd3.
Report an issue: GitHub.