nautechsystems/nautilus_trader · error · anyhow::Error

Data client factory '{name}' is already registered

Error message

Data client factory '{name}' is already registered

What it means

The DataClientFactoryRegistry::register method refuses to overwrite an existing factory: if `factories` already contains the given name it bails with this error instead of silently replacing the entry. Factory names act as unique keys, so re-registration under the same name is treated as a programming/config error.

Source

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

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

    /// Registers a data 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 DataClientFactory>,
    ) -> anyhow::Result<()> {
        if self.factories.contains_key(&name) {
            anyhow::bail!("Data client factory '{name}' is already registered");
        }

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

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

    /// Gets a list of all registered factory names.
    #[must_use]

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check `factories.contains_key(name)` (or a registry getter) before registering, and skip or log if present.
  2. Use a unique factory name (e.g. namespace it: 'myvendor-binance') instead of a name already in use.
  3. Restructure init so registration happens exactly once per registry instance.
  4. If replacement is genuinely intended, build a new registry or add a replace API rather than re-registering.

Example fix

// before
registry.register("Binance".to_string(), my_factory)?;

// after
if !registry.get("Binance") {
    registry.register("MyVendorBinance".to_string(), my_factory)?;
}
Defensive patterns

Strategy: validation

Validate before calling

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

Try / catch

match registry.register(name.clone(), factory) {
    Ok(()) => {}
    Err(e) if e.to_string().contains("already registered") => {
        log::debug!("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 DataClientFactoryRegistry instance, e.g. registering built-in factories and then a custom factory using an identical name string.

Common situations: Initializing a registry in multiple code paths (module init + user config) that both register the same factory name; a plugin registering a factory name that collides with a built-in; test helpers reusing a global registry across cases without clearing it.

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