nautechsystems/nautilus_trader · error

Invalid config type for BetfairExecutionClientFactory. Expec

Error message

Invalid config type for BetfairExecutionClientFactory. Expected BetfairExecConfig, was {config:?}

What it means

BetfairExecutionClientFactory::create tried to downcast the passed &dyn ClientConfig to BetfairExecConfig and failed — a different concrete config type was supplied. The execution client cannot be constructed from it, so factory creation fails at startup before any venue interaction.

Source

Thrown at crates/adapters/betfair/src/factories.rs:162

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

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

        betfair_config.validate()?;

        let credential = betfair_config.credential()?;
        let stream_config = betfair_config.stream_config();
        let currency = betfair_config.currency()?;

        let http_client = BetfairHttpClient::new(
            credential.clone(),
            None,
            None,
            None,
            betfair_config.proxy_url.clone(),
            Some(betfair_config.request_rate_per_second),

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Ensure the config-map entry routed to BetfairExecutionClientFactory is a BetfairExecConfig instance.
  2. Downcast-check the config before calling create when wiring factories manually.
  3. Verify the venue-to-factory-to-config triple in the node configuration.

Example fix

// before: map pairs exec factory with data config
config_map.insert("BETFAIR".to_string(), Box::new(BetfairDataConfig::default()));

// after
config_map.insert("BETFAIR".to_string(), Box::new(BetfairExecConfig::default()));
Defensive patterns

Strategy: type-guard

Validate before calling

let is_valid = config
    .as_any()
    .downcast_ref::<BetfairExecConfig>()
    .is_some();
if !is_valid {
    return Err(anyhow::anyhow!("expected BetfairExecConfig for execution factory"));
}

Type guard

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

Prevention

When it happens

Trigger: Registering BetfairExecutionClientFactory against a config map entry holding BetfairDataConfig or another venue's config; generic client-bootstrapping code that passes the wrong config object.

Common situations: Config-map wiring mistakes where data and exec entries were swapped; custom orchestration code that reuses one config instance for both factories.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/ffcf5c71505e94cd. Report an issue: GitHub.