nautechsystems/nautilus_trader · error · anyhow::Error

Invalid config type for BybitExecutionClientFactory. Expecte

Error message

Invalid config type for BybitExecutionClientFactory. Expected BybitExecutionClientConfig, was {config:?}

What it means

The BybitExecutionClientFactory.create() cannot downcast the supplied config to BybitExecutionClientConfig. Each execution factory expects its own concrete config type; any other DynData/ExecutionClientConfig implementation fails the downcast_ref and the factory returns an anyhow error embedding the Debug repr of what was actually passed.

Source

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

    #[must_use]
    pub const fn new() -> Self {
        Self
    }
}

impl ExecutionClientFactory for BybitExecutionClientFactory {
    fn create(
        &self,
        trader_id: TraderId,
        name: &str,
        config: &dyn ClientConfig,
        cache: CacheView,
    ) -> anyhow::Result<Box<dyn ExecutionClient>> {
        let bybit_config = config
            .as_any()
            .downcast_ref::<BybitExecutionClientConfig>()
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "Invalid config type for BybitExecutionClientFactory. Expected BybitExecutionClientConfig, was {config:?}",
                )
            })?
            .clone();

        // Default to Linear if product_types is empty (matches execution client behavior)
        let product_types = if bybit_config.product_types.is_empty() {
            vec![BybitProductType::Linear]
        } else {
            bybit_config.product_types.clone()
        };

        let has_derivatives = product_types.iter().any(|t| {
            matches!(
                t,
                BybitProductType::Linear | BybitProductType::Inverse | BybitProductType::Option
            )
        });

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the {config:?} debug output to identify the config type actually supplied
  2. Replace it with a properly constructed BybitExecutionClientConfig (including product_types, api credentials)
  3. Verify the factory-to-config pairing in your live node/cluster config file
  4. Rebuild any custom config wrappers so they serialize/deserialize as BybitExecutionClientConfig

Example fix

// before
let factory = BybitExecutionClientFactory::new();
let config = BybitDataClientConfig { api_key, api_secret, ..Default::default() };
let client = factory.create("BYBIT", config, cache, clock)?;
// after
let config = BybitExecutionClientConfig { api_key, api_secret, product_types: vec![BybitProductType::Linear], ..Default::default() };
let client = factory.create("BYBIT", config, cache, clock)?;
Defensive patterns

Strategy: type-guard

Validate before calling

fn ensure_bybit_exec_config(config: &dyn Any) -> Result<&BybitExecutionClientConfig, String> {
    config.downcast_ref::<BybitExecutionClientConfig>()
        .ok_or_else(|| "expected BybitExecutionClientConfig".to_string())
}

Type guard

fn is_bybit_exec_config(cfg: &dyn ExecutionClientConfig) -> bool {
    cfg.as_any().downcast_ref::<BybitExecutionClientConfig>().is_some()
}

Try / catch

let client = factory.create(name, config, cache, clock)
    .map_err(|e| anyhow::anyhow!("Bybit exec client init failed: {e}"))?;

Prevention

When it happens

Trigger: Registering BybitExecutionClientFactory with a BybitDataClientConfig, a base ExecutionClientConfig, or another adapter's execution config; swapping config structs in code without updating the factory; config deserialization producing the wrong concrete type for the 'bybit' execution client.

Common situations: Mixed-venue live cluster configs where the execution client section was left as another exchange's config; refactors that renamed/merged config types; hand-built ClientConfig objects passed to the wrong factory.

Related errors


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