nautechsystems/nautilus_trader · error · anyhow::Error

Execution client factory '{name}' is already registered

Error message

Execution client factory '{name}' is already registered

What it means

ExecutionClientFactoryRegistry::register likewise rejects duplicate names: registering an ExecutionClientFactory under a name already present in `factories` bails with this error. Each execution client factory must have a distinct name key so client resolution is deterministic.

Source

Thrown at crates/common/src/factories/client.rs:213

    #[must_use]
    pub fn new() -> Self {
        Self {
            factories: AHashMap::new(),
        }
    }

    /// Registers an execution client factory.
    ///
    /// # Errors
    ///
    /// Returns an error if a factory with the same name is already registered.
    pub fn register(
        &mut self,
        name: String,
        factory: Box<dyn ExecutionClientFactory>,
    ) -> anyhow::Result<()> {
        if self.factories.contains_key(&name) {
            anyhow::bail!("Execution client factory '{name}' is already registered");
        }

        self.factories.insert(name, factory);
        Ok(())
    }

    /// Gets a registered factory by name (if found).
    #[must_use]
    pub fn get(&self, name: &str) -> Option<&dyn ExecutionClientFactory> {
        self.factories.get(name).map(std::convert::AsRef::as_ref)
    }

    /// Gets a list of all registered factory names.
    #[must_use]
    pub fn names(&self) -> Vec<&String> {
        self.factories.keys().collect()
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check for the name before registering and skip or return early if already present.
  2. Rename one of the conflicting factories to a unique, namespaced name.
  3. Ensure execution factory registration occurs in a single place during node setup.
  4. If a global/static registry is shared, reset or recreate it between runs/tests.

Example fix

// before
exec_registry.register("Binance".to_string(), exec_factory)?;

// after
if !exec_registry.contains("Binance") {
    exec_registry.register("Binance".to_string(), exec_factory)?;
}
Defensive patterns

Strategy: validation

Validate before calling

// Rust
fn ensure_absent(registry: &ExecutionClientFactoryRegistry, name: &str) -> anyhow::Result<()> {
    if registry.contains(name) {
        anyhow::bail!("execution factory '{}' already registered; skipping", name);
    }
    Ok(())
}

Try / catch

match exec_registry.register(name.clone(), factory) {
    Ok(()) => {}
    Err(e) if e.to_string().contains("already registered") => {
        log::debug!("execution factory {name} already present; reusing existing");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `register(name, factory)` twice with the same `name` on the same ExecutionClientFactoryRegistry, e.g. both a built-in setup and user code registering an execution factory with the identical client name.

Common situations: A venue package that ships both data and execution factories where the execution one is registered twice (once by library init, once by the user); colliding plugin names; re-running registration logic on the same registry.

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