{"record":{"id":"ede5be20639701e2","repo":"nautechsystems/nautilus_trader","slug":"connection-rate-limiter-requires-at-least-one-conn","errorCode":null,"errorMessage":"Connection rate limiter requires at least one connection rate key","messagePattern":"Connection rate limiter requires at least one connection rate key","errorType":"exception","errorClass":"TransportError","httpStatus":null,"severity":"error","filePath":"crates/network/src/websocket/client.rs","lineNumber":2856,"sourceCode":"                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)>,\n        rate_limiter: Option<Arc<RateLimiter<Ustr, MonotonicClock>>>,\n    ) -> Result<Arc<RateLimiter<Ustr, MonotonicClock>>, TransportError> {\n        if let Some(rate_limiter) = rate_limiter {\n            if default_quota.is_some() || !keyed_quotas.is_empty() {\n                return Err(TransportError::Io(std::io::Error::new(\n                    std::io::ErrorKind::InvalidInput,\n                    \"Cannot combine a shared rate limiter with quota configuration\",","sourceCodeStart":2838,"sourceCodeEnd":2874,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/network/src/websocket/client.rs#L2838-L2874","documentation":"The mirror-side validation of resolve_connection_rate_limit: a connection rate limiter without at least one key has nothing to look up in the limiter, which is a configuration mistake. The builder rejects it at construction with this InvalidInput TransportError rather than creating a rate limiter that would never be consulted.","triggerScenarios":"Building WebSocketClient with Some(rate_limiter) but an empty connection_rate_keys slice.","commonSituations":"Constructing the limiter unconditionally but only filling keys conditionally (e.g. keys loaded from config that was empty); a refactor that separated limiter creation from key wiring; default limiter in a shared builder helper with per-environment key lists.","solutions":["Provide at least one connection rate key when configuring a rate limiter","If rate limiting is not needed, omit the limiter entirely instead of passing one with no keys","Make the config layer require key(s) whenever the limiter flag/section is present"],"exampleFix":"// before\nbuilder.connection_rate_limiter(limiter) // keys empty\n// after\nbuilder\n    .connection_rate_limiter(limiter)\n    .connection_rate_keys(Arc::from([ustr(\"default\")]))","handlingStrategy":"validation","validationCode":"if rate_limiter.is_some() && connection_rate_keys.is_empty() {\n    return Err(anyhow!(\"rate limiter set without connection rate keys\"));\n}","typeGuard":null,"tryCatchPattern":"match WebSocketClient::new(...) {\n    Err(e) if e.to_string().contains(\"requires at least one connection rate key\") => {\n        // supply keys or drop the limiter, then rebuild\n    }\n    r => r?,\n}","preventionTips":["Require key(s) in your config schema whenever the limiter section is present","Avoid default limiter construction in shared builders when keys come from config","Keep limiter and keys wiring in one code path so they cannot diverge"],"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-14T00:17:10.932Z"}