{"record":{"id":"5dc063a8270f9004","repo":"nautechsystems/nautilus_trader","slug":"cannot-combine-a-shared-rate-limiter-with-quota-co","errorCode":null,"errorMessage":"Cannot combine a shared rate limiter with quota configuration","messagePattern":"Cannot combine a shared rate limiter with quota configuration","errorType":"exception","errorClass":"TransportError","httpStatus":null,"severity":"error","filePath":"crates/network/src/websocket/client.rs","lineNumber":2872,"sourceCode":"\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\",\n                )));\n            }\n            return Ok(rate_limiter);\n        }\n\n        let keyed_quotas = keyed_quotas\n            .into_iter()\n            .map(|(key, quota)| (Ustr::from(&key), quota))\n            .collect();\n        Ok(Arc::new(RateLimiter::new_with_quota(\n            default_quota,\n            keyed_quotas,\n        )))\n    }\n\n    async fn connect_with_handler_scoped(","sourceCodeStart":2854,"sourceCodeEnd":2890,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/network/src/websocket/client.rs#L2854-L2890","documentation":"The WebSocket transport factory builds a rate limiter either from quota configuration (a default quota and/or per-key quotas) or accepts a caller-supplied shared Arc<RateLimiter>. These two configuration modes are mutually exclusive: if a pre-built rate limiter is provided while default_quota or keyed_quotas are also set, it cannot decide which policy wins, so it returns an Io InvalidInput error wrapped in TransportError.","triggerScenarios":"Calling the transport/factory constructor passing rate_limiter: Some(Arc<RateLimiter<...>>) together with a non-None default_quota or a non-empty keyed_quotas vec.","commonSituations":"Config files or environment-driven setups where a user pastes both a 'rate limiter' preset and quota settings; combining an adapter's built-in shared limiter with custom per-endpoint quotas; copying example code that already sets quotas while a shared limiter remains enabled from an earlier call.","solutions":["Remove the rate_limiter argument and configure only default_quota/keyed_quotas so the limiter is built from quotas.","Keep the shared rate_limiter and set default_quota to None and keyed_quotas to an empty vec.","If both behaviors are needed, merge the quotas into the shared RateLimiter's own configuration before wrapping it in Arc and passing it.","Pre-validate the config at startup and surface a clear user-facing message instead of relying on this transport error."],"exampleFix":"// before\nlet limiter = Some(Arc::new(RateLimiter::new(clock)));\nlet transport = build_transport(limiter, Some(default_quota), keyed_quotas); // errors\n// after\nlet transport = build_transport(None, Some(default_quota), keyed_quotas); // quotas build the limiter\n// or\nlet transport = build_transport(limiter, None, Vec::new()); // shared limiter only","handlingStrategy":"validation","validationCode":"if rate_limiter.is_some() && (default_quota.is_some() || !keyed_quotas.is_empty()) {\n    return Err(\"Provide either a shared rate_limiter OR quota configuration, not both\".into());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Model transport config as an enum (QuotaConfig | SharedLimiter) so an invalid combination is unrepresentable.","Validate the merged config once at startup before constructing transports.","Document in the config schema that rate_limiter excludes quota fields."],"tags":["websocket","rate-limiting","configuration-conflict","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"}