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
- Check `factories.contains_key(name)` (or a registry getter) before registering, and skip or log if present.
- Use a unique factory name (e.g. namespace it: 'myvendor-binance') instead of a name already in use.
- Restructure init so registration happens exactly once per registry instance.
- 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
- Register factories from a single init function.
- Namespace custom factory names to avoid collisions with built-ins.
- Check-before-insert for idempotent setup, especially with shared/global registries.
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
- Execution client factory '{name}' is already registered
- Invalid config type for AxExecutionClientFactory. Expected A
- Unsupported product type for Binance data client: {product_t
- Unsupported product type for Binance execution client: {prod
- Unsupported account_type {account_type:?} for Coinbase; expe
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/821da48f2152e2dc.
Report an issue: GitHub.