nautechsystems/nautilus_trader · error

Simulated execution factory extractor '{name}' is already re

Error message

Simulated execution factory extractor '{name}' is already registered

What it means

register_sim_exec_factory_extractor stores named simulated-execution factory extractors and rejects duplicate names. A second registration under an existing name would overwrite the original, so it is refused.

Source

Thrown at crates/system/src/python/registry.rs:138

        }
        extractors.insert(name, extractor);
        Ok(())
    }

    /// Registers a simulated execution factory extractor for a specific factory name.
    ///
    /// # Errors
    ///
    /// Returns an error if a factory with the same name is already registered.
    pub fn register_sim_exec_factory_extractor(
        &self,
        name: String,
        extractor: SimulatedExecutionFactoryExtractor,
    ) -> anyhow::Result<()> {
        let mut extractors = self.sim_exec_factory_extractors.lock();

        if extractors.contains_key(&name) {
            anyhow::bail!("Simulated execution factory extractor '{name}' is already registered");
        }
        extractors.insert(name, extractor);
        Ok(())
    }

    /// Extracts a `Py<PyAny>` factory to a boxed `DataClientFactory` trait object.
    ///
    /// # Errors
    ///
    /// Returns an error if no extractor is registered for the factory type or extraction fails.
    pub fn extract_factory(
        &self,
        py: Python<'_>,
        factory: Py<PyAny>,
    ) -> PyResult<Box<dyn DataClientFactory>> {
        // Get the factory name to find the appropriate extractor
        let factory_name = factory
            .getattr(py, "name")?

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Register once per process or make the registration call idempotent.
  2. Give custom sim factories unique names.
  3. Reset/rebuild the registry between runs instead of re-registering into it.

Example fix

// before
# notebook cell re-run
register_sim_exec_factory_extractor("SimExec", factory)
// after
if not registry.has_sim_exec_factory("SimExec"):
    register_sim_exec_factory_extractor("SimExec", factory)
Defensive patterns

Strategy: try-catch

Validate before calling

if name in registered_sim_exec_factories:
    return
registered_sim_exec_factories.add(name)
register_sim_exec_factory_extractor(name, factory)

Type guard

def sim_factory_registered(name: str, names: set) -> bool:
    return name in names

Try / catch

try:
    register_sim_exec_factory_extractor(name, factory)
except Exception as e:
    if "is already registered" in str(e):
        pass  # treat as idempotent
    else:
        raise

Prevention

When it happens

Trigger: Calling the public register_sim_exec_factory_extractor twice with the same `name` — module re-import, double setup of the sandbox/simulated venue stack, or name collision with another sim factory.

Common situations: Test suites that rebuild nodes per test without clearing the registry, notebooks re-running setup cells, custom sim fill-model adapters registered per-test.

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


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