{"record":{"id":"80ad4facef2a79e7","repo":"nautechsystems/nautilus_trader","slug":"invalid-config-type-for-bybitdataclientfactory-ex","errorCode":null,"errorMessage":"Invalid config type for BybitDataClientFactory. Expected BybitDataClientConfig, was {config:?}","messagePattern":"Invalid config type for BybitDataClientFactory\\. Expected BybitDataClientConfig, was (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/bybit/src/factories.rs","lineNumber":92,"sourceCode":"impl Default for BybitDataClientFactory {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl DataClientFactory for BybitDataClientFactory {\n    fn create(\n        &self,\n        name: &str,\n        config: &dyn ClientConfig,\n        _cache: CacheView,\n        _clock: Rc<RefCell<dyn Clock>>,\n    ) -> anyhow::Result<Box<dyn DataClient>> {\n        let bybit_config = config\n            .as_any()\n            .downcast_ref::<BybitDataClientConfig>()\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"Invalid config type for BybitDataClientFactory. Expected BybitDataClientConfig, was {config:?}\",\n                )\n            })?\n            .clone();\n\n        let client_id = ClientId::from(name);\n        let client = BybitDataClient::new(client_id, bybit_config)?;\n        Ok(Box::new(client))\n    }\n\n    fn name(&self) -> &'static str {\n        BYBIT\n    }\n\n    fn config_type(&self) -> &'static str {\n        \"BybitDataClientConfig\"\n    }\n}","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bybit/src/factories.rs#L74-L110","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the {config:?} debug output in the message to see the actual config type passed","Change the data client config for this factory instance to BybitDataClientConfig","If using TOML/JSON config, fix the data client section so it deserializes as BybitDataClientConfig under the bybit factory","Ensure the factory name ('bybit') matches the config type registered for that client"],"exampleFix":"// before\n\"data_clients\": {\n    \"MyBybit\": { \"factory\": \"BybitDataClientFactory\", \"config\": { \"type\": \"DataClientConfig\" } }\n}\n// after\n\"data_clients\": {\n    \"MyBybit\": { \"factory\": \"BybitDataClientFactory\", \"config\": { \"type\": \"BybitDataClientConfig\", \"api_key\": \"...\", \"api_secret\": \"...\" } }\n}","handlingStrategy":"type-guard","validationCode":"use std::any::Any;\nfn ensure_bybit_data_config(config: &dyn Any) -> Result<&BybitDataClientConfig, String> {\n    config.downcast_ref::<BybitDataClientConfig>()\n        .ok_or_else(|| format!(\"expected BybitDataClientConfig, got {:?}\", config.type_id()))\n}","typeGuard":"fn is_bybit_data_config(cfg: &dyn DataClientConfig) -> bool {\n    cfg.as_any().downcast_ref::<BybitDataClientConfig>().is_some()\n}","tryCatchPattern":"match factory.create(name, config, clock) {\n    Ok(client) => client,\n    Err(e) if e.to_string().contains(\"Invalid config type\") => {\n        eprintln!(\"config/type mismatch for Bybit data client: {e}\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep factory name and config type paired in one place (a registration helper)","Validate config files against the expected schema before building live nodes","Add a startup assertion that each factory receives its matching config type"],"tags":["rust","config","downcast","bybit"],"backgroundTag":"config-type-mismatch","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}