nautechsystems/nautilus_trader · error · anyhow::Error

A different simulation module extractor is already registere

Error message

A different simulation module extractor is already registered for '{type_name}'

What it means

register_simulation_module_extractor registers a Python-side extractor for a simulation module type, keyed by the type's TypeId in a global registry. If a type is registered a second time with a DIFFERENT extractor function, registration fails; re-registering the identical extractor is a no-op that returns Ok. This guards against one module silently overriding another's extractor.

Source

Thrown at crates/backtest/src/python/modules.rs:74

///
/// Registering the same function for the same Python type more than once succeeds without change.
///
/// # Errors
///
/// Returns an error if a different extractor is already registered for `T`.
pub fn register_simulation_module_extractor<T: PyClass>(
    py: Python<'_>,
    extractor: SimulationModuleExtractor,
) -> anyhow::Result<()> {
    let type_object = py.get_type::<T>();
    let type_id = type_object.as_ptr() as usize;
    let type_name = type_object.name()?;
    let mut extractors = SIMULATION_MODULE_EXTRACTORS.lock();
    if let Some(registered) = extractors.get(&type_id) {
        if std::ptr::fn_addr_eq(*registered, extractor) {
            return Ok(());
        }
        anyhow::bail!(
            "A different simulation module extractor is already registered for '{type_name}'"
        );
    }
    extractors.insert(type_id, extractor);
    Ok(())
}

#[pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.backtest")]
#[pyclass(
    module = "nautilus_trader.backtest",
    name = "SimulationModule",
    subclass
)]
#[derive(Debug)]
pub struct PySimulationModule;

#[pyo3_stub_gen::derive::gen_stub_pymethods]
#[pymethods]

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Register each type's extractor exactly once at process startup, before simulation runs
  2. If the different extractor is intentional, remove the previous registration or use a distinct Python type
  3. Check for duplicate imports/plugins that both call register_simulation_module_extractor for the same type
  4. If re-registering the same extractor, no error occurs — ensure you pass the identical function object, not a re-created wrapper

Example fix

// before
register_simulation_module_extractor(MyModule, my_extractor_v1)
register_simulation_module_extractor(MyModule, my_extractor_v2)  # bails
// after
register_simulation_module_extractor(MyModule, my_extractor_v2)  # register once, final version
Defensive patterns

Strategy: validation

Validate before calling

def ensure_registered(type_obj, extractor, _seen={}):
    key = type_obj
    if key in _seen and _seen[key] is not extractor:
        raise RuntimeError(f"extractor already registered differently for {type_obj.__name__}")
    _seen[key] = extractor

Prevention

When it happens

Trigger: Calling register_simulation_module_extractor twice for the same Python type with two different extractor callables, or two libraries importing the same type and each installing their own extractor.

Common situations: Loading multiple plugin packages that both extend the same simulation module type; re-registering during a test harness with a freshly defined but semantically different extractor; hot-reloading a module whose extractor closure changed.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/7a23bfd6bc42b0d0. Report an issue: GitHub.