{"record":{"id":"5abacdac8631714d","repo":"nautechsystems/nautilus_trader","slug":"cannot-configure-both-ping-handler-and-epoch-ping","errorCode":null,"errorMessage":"Cannot configure both ping_handler and epoch_ping_handler","messagePattern":"Cannot configure both ping_handler and epoch_ping_handler","errorType":"exception","errorClass":"TransportError","httpStatus":null,"severity":"error","filePath":"crates/network/src/websocket/client.rs","lineNumber":2817,"sourceCode":"        finish_fn = connect\n    )]\n    pub async fn epoch_builder(\n        config: WebSocketConfig,\n        epoch_handler: EpochMessageHandler,\n        ping_handler: Option<PingHandler>,\n        epoch_ping_handler: Option<EpochPingHandler>,\n        #[builder(default)] keyed_quotas: Vec<(String, Quota)>,\n        default_quota: Option<Quota>,\n        rate_limiter: Option<Arc<RateLimiter<Ustr, MonotonicClock>>>,\n        state_sink: Option<SocketStateSink>,\n        connection_rate_limiter: Option<Arc<RateLimiter<Ustr, MonotonicClock>>>,\n        #[builder(default)] connection_rate_keys: Arc<[Ustr]>,\n        initial_connect_retry_policy: Option<InitialConnectRetryPolicy>,\n        cancellation_token: Option<CancellationToken>,\n    ) -> Result<Self, TransportError> {\n        let ping_handler = match (ping_handler, epoch_ping_handler) {\n            (Some(_), Some(_)) => {\n                return Err(TransportError::Io(std::io::Error::new(\n                    std::io::ErrorKind::InvalidInput,\n                    \"Cannot configure both ping_handler and epoch_ping_handler\",\n                )));\n            }\n            (Some(handler), None) => Some(IncomingPingHandler::Ping(handler)),\n            (None, Some(handler)) => Some(IncomingPingHandler::Epoch(handler)),\n            (None, None) => None,\n        };\n        let rate_limiter = Self::resolve_rate_limiter(default_quota, keyed_quotas, rate_limiter)?;\n        let connection_rate_limit =\n            Self::resolve_connection_rate_limit(connection_rate_limiter, connection_rate_keys)?;\n        Self::connect_with_handler_scoped(\n            config,\n            IncomingHandler::Epoch(epoch_handler),\n            ping_handler,\n            rate_limiter,\n            state_sink,\n            connection_rate_limit,","sourceCodeStart":2799,"sourceCodeEnd":2835,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/network/src/websocket/client.rs#L2799-L2835","documentation":"The WebSocketClient builder accepts two mutually exclusive incoming-ping mechanisms: a plain ping_handler and an epoch_ping_handler (which receives the connection epoch). Supplying both is an invalid configuration, rejected at build time with this InvalidInput TransportError before any connection is made. The client cannot represent both handler styles simultaneously, so the configuration is refused early.","triggerScenarios":"Calling WebSocketClient::new (builder) with Some(...) for both ping_handler and epoch_ping_handler parameters.","commonSituations":"Migrating code from the legacy ping_handler to epoch_ping_handler but leaving both set in config; a shared config layer that populates both from different sources; copy-paste wiring that forwards the existing handler plus a new epoch-aware one.","solutions":["Remove the legacy ping_handler and keep only epoch_ping_handler if you need epoch context","Keep only ping_handler if epoch tracking is unnecessary","Centralize handler selection in one config path so only one is ever populated","At your config layer, treat the two fields as mutually exclusive and error early with a clear message"],"exampleFix":"// before\nWebSocketClient::new(..., Some(ping_handler), Some(epoch_ping_handler), ...)?\n// after\nWebSocketClient::new(..., None, Some(epoch_ping_handler), ...)?","handlingStrategy":"validation","validationCode":"if ping_handler.is_some() && epoch_ping_handler.is_some() {\n    return Err(anyhow!(\"only one of ping_handler / epoch_ping_handler may be set\"));\n}","typeGuard":null,"tryCatchPattern":"match WebSocketClient::new(..., ping_handler, epoch_ping_handler, ...) {\n    Err(e) if e.to_string().contains(\"both ping_handler\") => {\n        // fix config: drop the legacy handler and retry construction\n    }\n    r => r?,\n}","preventionTips":["During migration to epoch_ping_handler, delete the legacy handler rather than keeping both","Model the two options as a single enum in your own config layer","Add a config-load-time assertion that at most one is set"],"tags":["websocket","configuration","mutually-exclusive","rust"],"backgroundTag":"mutually-exclusive-options","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"}