nautechsystems/nautilus_trader · error

Factory extractor '{name}' is already registered

Error message

Factory extractor '{name}' is already registered

What it means

register_factory_extractor stores named factory extractors in a mutex-guarded map and rejects duplicate names. This error means some code attempted to register a second extractor under an already-used name, which would silently overwrite the first.

Source

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

            sim_exec_factory_extractors: Mutex::new(HashMap::new()),
            config_extractors_by_type: Mutex::new(HashMap::new()),
        }
    }

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

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

    /// Registers a config extractor for a specific config type name.
    ///
    /// # Errors
    ///
    /// Returns an error if a config with the same type name is already registered.
    pub fn register_config_extractor(
        &self,
        type_name: String,
        extractor: ConfigExtractor,
    ) -> anyhow::Result<()> {
        let mut extractors = self.config_extractors_by_type.lock();

        if extractors.contains_key(&type_name) {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Guard registration with a check or only register once per process.
  2. Use a unique, namespaced factory name for custom extractors.
  3. If a module reload is causing it, skip re-registration (idempotent init).

Example fix

// before
registry.register_factory_extractor("MyDataClient", extractor)?;
registry.register_factory_extractor("MyDataClient", extractor)?; // panics/bails
// after
if !registered.contains("MyDataClient") {
    registry.register_factory_extractor("MyDataClient", extractor)?;
}
Defensive patterns

Strategy: try-catch

Validate before calling

# Python
def register_once(name, extractor):
    if name in registered_factory_extractors:
        return
    registered_factory_extractors.add(name)
    register_factory_extractor(name, extractor)

Type guard

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

Try / catch

try:
    register_factory_extractor(name, extractor)
except Exception as e:
    if "is already registered" in str(e):
        log.debug("Factory extractor %s already registered; skipping", name)
    else:
        raise

Prevention

When it happens

Trigger: Calling the public register_factory_extractor twice with the same `name` — typically module re-initialization, double plugin import, or two libraries registering the same factory name (e.g. two versions of a client adapter).

Common situations: Hot-reloading a Python extension module that re-runs registration code, importing a custom client factory plugin twice, or colliding names between in-house and third-party factories.

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/64e8282733e06ca6. Report an issue: GitHub.