{"record":{"id":"10dcf1715cc16e3b","repo":"nautechsystems/nautilus_trader","slug":"invalid-max-requests-per-second-max-requests-per","errorCode":null,"errorMessage":"Invalid max_requests_per_second: {max_requests_per_second} exceeds maximum","messagePattern":"Invalid max_requests_per_second: (.+?) exceeds maximum","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/kraken/src/http/futures/client.rs","lineNumber":277,"sourceCode":"\n    /// Returns a clone of the current cancellation token.\n    pub fn cancellation_token(&self) -> CancellationToken {\n        self.cancellation_token.read().clone()\n    }\n\n    fn default_headers() -> HashMap<String, String> {\n        HashMap::from([(USER_AGENT.to_string(), NAUTILUS_USER_AGENT.to_string())])\n    }\n\n    fn default_quota(max_requests_per_second: u32) -> anyhow::Result<Quota> {\n        let burst = NonZeroU32::new(max_requests_per_second).unwrap_or(\n            NonZeroU32::new(KRAKEN_FUTURES_DEFAULT_RATE_LIMIT_PER_SECOND).expect(\"non-zero\"),\n        );\n        Quota::per_second(burst).ok_or_else(|| {\n            anyhow::anyhow!(\n                \"Invalid max_requests_per_second: {max_requests_per_second} exceeds maximum\"\n            )\n        })\n    }\n\n    fn rate_limiter_quotas(max_requests_per_second: u32) -> anyhow::Result<Vec<(String, Quota)>> {\n        Ok(vec![(\n            KRAKEN_GLOBAL_RATE_KEY.to_string(),\n            Self::default_quota(max_requests_per_second)?,\n        )])\n    }\n\n    fn rate_limit_keys(endpoint: &str) -> Vec<String> {\n        let normalized = endpoint.split('?').next().unwrap_or(endpoint);\n        let route = format!(\"kraken:futures:{normalized}\");\n        vec![KRAKEN_GLOBAL_RATE_KEY.to_string(), route]\n    }\n\n    async fn send_request<T: DeserializeOwned>(\n        &self,\n        method: Method,","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/kraken/src/http/futures/client.rs#L259-L295","documentation":"Raised by default_quota when the requested max_requests_per_second is so large that governor's Quota::per_second cannot represent the burst capacity. The rate limiter cannot be constructed, so the client refuses the configuration.","triggerScenarios":"Calling default_quota / rate_limiter_quotas with a max_requests_per_second whose burst exceeds the representable quota range — practically, an absurdly large value like u32::MAX or a misparsed config value.","commonSituations":"Passing 0-overflowing or sentinel values from config files; unit confusion (requests per minute supplied as per-second); programmatic config generation producing huge numbers.","solutions":["Set max_requests_per_second to a realistic per-second value (Kraken Futures default is a small tens value).","Check config parsing: confirm the value is requests/second, not per-minute or per-hour.","Clamp the configured value before constructing the client."],"exampleFix":"// before\nlet max_rps = env::var(\"KRAKEN_MAX_RPS\").unwrap().parse::<u32>()?; // could be huge\n// after\nlet max_rps = env::var(\"KRAKEN_MAX_RPS\").unwrap().parse::<u32>()?.min(100);","handlingStrategy":"validation","validationCode":"let max_rps = max_requests_per_second.min(100);\nassert!(max_rps > 0, \"max_requests_per_second must be positive\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Document the unit (per second) next to the config field to avoid per-minute confusion.","Clamp user-supplied rate limits to a safe maximum before client construction.","Reject obviously wrong values (0, u32::MAX) during config validation."],"tags":["rate-limit","config","kraken","futures","value-out-of-range"],"backgroundTag":"value-out-of-range","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"}