nautechsystems/nautilus_trader · error

Invalid config type for CoinbaseDataClientFactory. Expected

Error message

Invalid config type for CoinbaseDataClientFactory. Expected CoinbaseDataClientConfig, was {config:?}

What it means

CoinbaseDataClientFactory::create downcasts the generic ClientConfig to CoinbaseDataClientConfig; if the downcast fails it rejects the config with this error. It is a type-safety guard ensuring the factory only builds Coinbase data clients from matching config types.

Source

Thrown at crates/adapters/coinbase/src/factories.rs:91

impl Default for CoinbaseDataClientFactory {
    fn default() -> Self {
        Self::new()
    }
}

impl DataClientFactory for CoinbaseDataClientFactory {
    fn create(
        &self,
        name: &str,
        config: &dyn ClientConfig,
        _cache: CacheView,
        _clock: Rc<RefCell<dyn Clock>>,
    ) -> anyhow::Result<Box<dyn DataClient>> {
        let coinbase_config = config
            .as_any()
            .downcast_ref::<CoinbaseDataClientConfig>()
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "Invalid config type for CoinbaseDataClientFactory. Expected CoinbaseDataClientConfig, was {config:?}",
                )
            })?
            .clone();

        let client_id = ClientId::from(name);
        let client = CoinbaseDataClient::new(client_id, coinbase_config)?;
        Ok(Box::new(client))
    }

    fn name(&self) -> &'static str {
        COINBASE
    }

    fn config_type(&self) -> &'static str {
        "CoinbaseDataClientConfig"
    }
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass a CoinbaseDataClientConfig instance to the data factory's create().
  2. Check your node/trading config file that the data-client section uses the Coinbase data client config schema.
  3. Verify factory registration pairs the correct config type with the correct factory.
  4. After upgrading nautilus, re-check config struct names for renames in the coinbase adapter.

Example fix

// before
factory.create(name, &coinbase_exec_config, ...)?;
// after
let data_config = CoinbaseDataClientConfig::from(coinbase_exec_config.clone());
factory.create(name, &data_config, ...)?;
Defensive patterns

Strategy: type-guard

Validate before calling

let is_data_cfg = config.as_any().downcast_ref::<CoinbaseDataClientConfig>().is_some();
if !is_data_cfg { /* route to execution factory or fix config wiring */ }

Type guard

fn is_coinbase_data_config(config: &dyn ClientConfig) -> bool {
    config.as_any().downcast_ref::<CoinbaseDataClientConfig>().is_some()
}

Try / catch

match factory.create(name, config, ...) {
    Ok(c) => c,
    Err(e) if e.to_string().contains("Invalid config type for CoinbaseDataClientFactory") => bail!("wired wrong config type to data factory: {e}"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Registering the Coinbase data factory but passing a different config type (e.g. CoinbaseExecutionClientConfig or another venue's config) to create(), or tests that deliberately pass a wrong config type.

Common situations: Mixing up data vs execution config in a node config file, wiring the wrong factory to the wrong config section, or renaming/moving config types after an adapter upgrade.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/01311ab6bdb3c128. Report an issue: GitHub.