nautechsystems/nautilus_trader · error

Config extractor '{type_name}' is already registered

Error message

Config extractor '{type_name}' is already registered

What it means

Registry duplicate guard: config extractors are keyed by config type name and each name may be registered once; a second registration of the same type_name is rejected to prevent silently overwriting an extractor.

Source

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

        }
        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) {
            anyhow::bail!("Config extractor '{type_name}' is already registered");
        }

        extractors.insert(type_name, extractor);
        Ok(())
    }

    /// Registers an 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_exec_factory_extractor(
        &self,
        name: String,
        extractor: ExecutionFactoryExtractor,
    ) -> anyhow::Result<()> {
        let mut extractors = self.exec_factory_extractors.lock();

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Register each config extractor only once (idempotent module init).
  2. Ensure config classes have unique fully-qualified type names.
  3. Namespace custom config extractor type names.

Example fix

// before
registry.register_config_extractor("StrategyConfig", extractor)?;
registry.register_config_extractor("StrategyConfig", other)?;
// after
registry.register_config_extractor("myapp.StrategyConfig", extractor)?;
Defensive patterns

Strategy: try-catch

Validate before calling

qualified = f"{type(config).__module__}.{type(config).__name__}"
if qualified in registered_config_extractors:
    return
registered_config_extractors.add(qualified)
register_config_extractor(qualified, extractor)

Type guard

def config_extractor_registered(type_name: str, names: set) -> bool:
    return type_name in names

Try / catch

try:
    register_config_extractor(type_name, extractor)
except Exception as e:
    if "is already registered" in str(e):
        log.debug("Config extractor %s skipped (duplicate)", type_name)
    else:
        raise

Prevention

When it happens

Trigger: Calling the public register_config_extractor twice with the same `type_name` — e.g. re-importing a module that registers extractors, or two config classes sharing the same qualified name (same module name in different packages).

Common situations: Extension module re-initialization, duplicated class names across packages shadowing each other, plugin loading the same config class twice.

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