{"record":{"id":"ffcf5c71505e94cd","repo":"nautechsystems/nautilus_trader","slug":"invalid-config-type-for-betfairexecutionclientfact","errorCode":null,"errorMessage":"Invalid config type for BetfairExecutionClientFactory. Expected BetfairExecConfig, was {config:?}","messagePattern":"Invalid config type for BetfairExecutionClientFactory\\. Expected BetfairExecConfig, was (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/betfair/src/factories.rs","lineNumber":162,"sourceCode":"\nimpl Default for BetfairExecutionClientFactory {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl ExecutionClientFactory for BetfairExecutionClientFactory {\n    fn create(\n        &self,\n        name: &str,\n        config: &dyn ClientConfig,\n        cache: CacheView,\n    ) -> anyhow::Result<Box<dyn ExecutionClient>> {\n        let betfair_config = config\n            .as_any()\n            .downcast_ref::<BetfairExecConfig>()\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"Invalid config type for BetfairExecutionClientFactory. Expected BetfairExecConfig, was {config:?}\",\n                )\n            })?\n            .clone();\n\n        betfair_config.validate()?;\n\n        let credential = betfair_config.credential()?;\n        let stream_config = betfair_config.stream_config();\n        let currency = betfair_config.currency()?;\n\n        let http_client = BetfairHttpClient::new(\n            credential.clone(),\n            None,\n            None,\n            None,\n            betfair_config.proxy_url.clone(),\n            Some(betfair_config.request_rate_per_second),","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/crates/adapters/betfair/src/factories.rs#L144-L180","documentation":"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.","triggerScenarios":"Registering BetfairExecutionClientFactory against a config map entry holding BetfairDataConfig or another venue's config; generic client-bootstrapping code that passes the wrong config object.","commonSituations":"Config-map wiring mistakes where data and exec entries were swapped; custom orchestration code that reuses one config instance for both factories.","solutions":["Ensure the config-map entry routed to BetfairExecutionClientFactory is a BetfairExecConfig instance.","Downcast-check the config before calling create when wiring factories manually.","Verify the venue-to-factory-to-config triple in the node configuration."],"exampleFix":"// before: map pairs exec factory with data config\nconfig_map.insert(\"BETFAIR\".to_string(), Box::new(BetfairDataConfig::default()));\n\n// after\nconfig_map.insert(\"BETFAIR\".to_string(), Box::new(BetfairExecConfig::default()));","handlingStrategy":"type-guard","validationCode":"let is_valid = config\n    .as_any()\n    .downcast_ref::<BetfairExecConfig>()\n    .is_some();\nif !is_valid {\n    return Err(anyhow::anyhow!(\"expected BetfairExecConfig for execution factory\"));\n}","typeGuard":"fn is_betfair_exec_config(config: &dyn ClientConfig) -> bool {\n    config.as_any().downcast_ref::<BetfairExecConfig>().is_some()\n}","tryCatchPattern":null,"preventionTips":["Pair BetfairExecutionClientFactory exclusively with BetfairExecConfig in the config map.","Add integration tests that bootstrap the full node config to catch downcast mismatches at build time.","Review custom bootstrap code whenever factories are added or reordered."],"tags":["betfair","config","factory","downcast","bootstrap"],"backgroundTag":"config-type-mismatch","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}