nautechsystems/nautilus_trader · error · anyhow::Error

Invalid config type for BybitDataClientFactory. Expected Byb

Error message

Invalid config type for BybitDataClientFactory. Expected BybitDataClientConfig, was {config:?}

What it means

The BybitDataClientFactory.create() receives a config object that it cannot downcast to BybitDataClientConfig via as_any().downcast_ref(). This means the DataClientConfig registered in the system/cluster config for this factory is a different concrete type. The factory bails with anyhow::anyhow! including the Debug representation of the actual config so you can see what type was passed.

Source

Thrown at crates/adapters/bybit/src/factories.rs:92

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

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

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

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

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

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the {config:?} debug output in the message to see the actual config type passed
  2. Change the data client config for this factory instance to BybitDataClientConfig
  3. If using TOML/JSON config, fix the data client section so it deserializes as BybitDataClientConfig under the bybit factory
  4. Ensure the factory name ('bybit') matches the config type registered for that client

Example fix

// before
"data_clients": {
    "MyBybit": { "factory": "BybitDataClientFactory", "config": { "type": "DataClientConfig" } }
}
// after
"data_clients": {
    "MyBybit": { "factory": "BybitDataClientFactory", "config": { "type": "BybitDataClientConfig", "api_key": "...", "api_secret": "..." } }
}
Defensive patterns

Strategy: type-guard

Validate before calling

use std::any::Any;
fn ensure_bybit_data_config(config: &dyn Any) -> Result<&BybitDataClientConfig, String> {
    config.downcast_ref::<BybitDataClientConfig>()
        .ok_or_else(|| format!("expected BybitDataClientConfig, got {:?}", config.type_id()))
}

Type guard

fn is_bybit_data_config(cfg: &dyn DataClientConfig) -> bool {
    cfg.as_any().downcast_ref::<BybitDataClientConfig>().is_some()
}

Try / catch

match factory.create(name, config, clock) {
    Ok(client) => client,
    Err(e) if e.to_string().contains("Invalid config type") => {
        eprintln!("config/type mismatch for Bybit data client: {e}");
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing a base DataClientConfig (or another venue's config, e.g. BinanceDataClientConfig) as the data client config while naming the Bybit factory; programmatic construction where the config struct was swapped; deserialized TOML/JSON config whose 'data_client' section maps to the wrong config type for the 'bybit' factory name.

Common situations: Copy-pasting a node config between venues without changing the config section; renaming the factory but not the config type; using a generic LiveNodeConfig builder where config types aren't statically checked.

Related errors


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