nautechsystems/nautilus_trader · error

Simulated execution factory extractor

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.

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.

Appendix: 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)