{"record":{"id":"251bbddf7bbe4a0b","repo":"nautechsystems/nautilus_trader","slug":"connection-rate-keys-require-a-connection-rate-lim","errorCode":null,"errorMessage":"Connection rate keys require a connection rate limiter","messagePattern":"Connection rate keys require a connection rate limiter","errorType":"exception","errorClass":"TransportError","httpStatus":null,"severity":"error","filePath":"crates/network/src/websocket/client.rs","lineNumber":2849,"sourceCode":"            IncomingHandler::Epoch(epoch_handler),\n            ping_handler,\n            rate_limiter,\n            state_sink,\n            connection_rate_limit,\n            InitialConnectOptions {\n                retry_policy: initial_connect_retry_policy,\n                cancellation_token,\n            },\n        )\n        .await\n    }\n\n    fn resolve_connection_rate_limit(\n        rate_limiter: Option<Arc<RateLimiter<Ustr, MonotonicClock>>>,\n        keys: Arc<[Ustr]>,\n    ) -> Result<Option<ConnectionRateLimit>, TransportError> {\n        if rate_limiter.is_none() && !keys.is_empty() {\n            return Err(TransportError::Io(std::io::Error::new(\n                std::io::ErrorKind::InvalidInput,\n                \"Connection rate keys require a connection rate limiter\",\n            )));\n        }\n\n        if rate_limiter.is_some() && keys.is_empty() {\n            return Err(TransportError::Io(std::io::Error::new(\n                std::io::ErrorKind::InvalidInput,\n                \"Connection rate limiter requires at least one connection rate key\",\n            )));\n        }\n\n        Ok(rate_limiter.map(|limiter| ConnectionRateLimit { limiter, keys }))\n    }\n\n    fn resolve_rate_limiter(\n        default_quota: Option<Quota>,\n        keyed_quotas: Vec<(String, Quota)>,","sourceCodeStart":2831,"sourceCodeEnd":2867,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/network/src/websocket/client.rs#L2831-L2867","documentation":"resolve_connection_rate_limit enforces that connection rate keys are only meaningful alongside a rate limiter: keys select which entries in the limiter are consulted. If keys are provided but rate_limiter is None, the configuration is incomplete and this InvalidInput TransportError is returned at client construction. Providing keys without a limiter would silently do nothing, so the builder rejects it instead.","triggerScenarios":"Building WebSocketClient with a non-empty connection_rate_keys Arc<[Ustr]> but no rate_limiter (Option<Arc<RateLimiter<Ustr, MonotonicClock>>> = None).","commonSituations":"Config layers that populate rate keys from config but construct the limiter only under a separate flag; disabling the limiter for dev environments while leaving keys set; copy-paste of key lists without the limiter setup.","solutions":["Supply a RateLimiter instance alongside the connection_rate_keys","If rate limiting is not wanted, clear the connection_rate_keys list","Make your config layer construct limiter and keys together as one unit"],"exampleFix":"// before\nbuilder.connection_rate_keys(keys) // no limiter set\n// after\nbuilder\n    .connection_rate_limiter(Arc::new(RateLimiter::new(clock)))\n    .connection_rate_keys(keys)","handlingStrategy":"validation","validationCode":"if rate_limiter.is_none() && !connection_rate_keys.is_empty() {\n    return Err(anyhow!(\"connection_rate_keys set without a rate limiter\"));\n}","typeGuard":null,"tryCatchPattern":"match WebSocketClient::new(...) {\n    Err(e) if e.to_string().contains(\"require a connection rate limiter\") => {\n        // either supply a limiter or clear keys, then rebuild\n    }\n    r => r?,\n}","preventionTips":["Treat limiter and keys as a single config unit; construct them together","When disabling rate limiting for dev, clear keys too","Validate the pair at config-load time before building the client"],"tags":["websocket","configuration","rate-limiting","validation","rust"],"backgroundTag":"conflicting-config-options","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}