nautechsystems/nautilus_trader · error

Invalid config type for BlockchainDataClientFactory. Expecte

Error message

Invalid config type for BlockchainDataClientFactory. Expected `BlockchainDataClientConfig`, was {config:?}

What it means

BlockchainDataClientFactory.create downcasts the passed config object to BlockchainDataClientConfig. This error fires when the config object supplied to the factory is of a different concrete type, so the downcast_ref returns None.

Source

Thrown at crates/adapters/blockchain/src/factories.rs:86

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

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

        let client = BlockchainDataClient::new(ClientId::from(name), blockchain_config.clone());

        Ok(Box::new(client))
    }

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

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

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass a BlockchainDataClientConfig instance to the data client factory
  2. Check the factory registration: data client factories must be paired with data client configs
  3. Print the config's concrete type and compare with BlockchainDataClientConfig
  4. Fix the config deserialization so it produces BlockchainDataClientConfig

Example fix

// before
factory.create(name, &other_config, ...) // other_config: BlockchainExecutionClientConfig
// after
let config = BlockchainDataClientConfig { /* ... */ };
factory.create(name, &config, ...)
Defensive patterns

Strategy: type-guard

Validate before calling

if config.as_any().downcast_ref::<BlockchainDataClientConfig>().is_none() {
    panic!("data client factory requires BlockchainDataClientConfig, got {:?}", config);
}

Type guard

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

Try / catch

// wrap factory.create in error context
let client = factory.create(name, &config, ...)
    .map_err(|e| anyhow::anyhow!("data client factory rejected config: {e:#}"))?;

Prevention

When it happens

Trigger: Calling BlockchainDataClientFactory.create (or the node factory registration path) with a config that is not a BlockchainDataClientConfig instance.

Common situations: Wiring the factory in a node builder but registering a generic/other client's config (e.g. an execution client config or a hand-rolled config struct); copy-pasted factory registration with the wrong config type; config deserialized into the wrong type.

Related errors


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