nautechsystems/nautilus_trader · error · anyhow::Error

Invalid max_requests_per_second: {max_requests_per_second} e

Error message

Invalid max_requests_per_second: {max_requests_per_second} exceeds maximum

What it means

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.

Source

Thrown at crates/adapters/kraken/src/http/futures/client.rs:277

    /// Returns a clone of the current cancellation token.
    pub fn cancellation_token(&self) -> CancellationToken {
        self.cancellation_token.read().clone()
    }

    fn default_headers() -> HashMap<String, String> {
        HashMap::from([(USER_AGENT.to_string(), NAUTILUS_USER_AGENT.to_string())])
    }

    fn default_quota(max_requests_per_second: u32) -> anyhow::Result<Quota> {
        let burst = NonZeroU32::new(max_requests_per_second).unwrap_or(
            NonZeroU32::new(KRAKEN_FUTURES_DEFAULT_RATE_LIMIT_PER_SECOND).expect("non-zero"),
        );
        Quota::per_second(burst).ok_or_else(|| {
            anyhow::anyhow!(
                "Invalid max_requests_per_second: {max_requests_per_second} exceeds maximum"
            )
        })
    }

    fn rate_limiter_quotas(max_requests_per_second: u32) -> anyhow::Result<Vec<(String, Quota)>> {
        Ok(vec![(
            KRAKEN_GLOBAL_RATE_KEY.to_string(),
            Self::default_quota(max_requests_per_second)?,
        )])
    }

    fn rate_limit_keys(endpoint: &str) -> Vec<String> {
        let normalized = endpoint.split('?').next().unwrap_or(endpoint);
        let route = format!("kraken:futures:{normalized}");
        vec![KRAKEN_GLOBAL_RATE_KEY.to_string(), route]
    }

    async fn send_request<T: DeserializeOwned>(
        &self,
        method: Method,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set max_requests_per_second to a realistic per-second value (Kraken Futures default is a small tens value).
  2. Check config parsing: confirm the value is requests/second, not per-minute or per-hour.
  3. Clamp the configured value before constructing the client.

Example fix

// before
let max_rps = env::var("KRAKEN_MAX_RPS").unwrap().parse::<u32>()?; // could be huge
// after
let max_rps = env::var("KRAKEN_MAX_RPS").unwrap().parse::<u32>()?.min(100);
Defensive patterns

Strategy: validation

Validate before calling

let max_rps = max_requests_per_second.min(100);
assert!(max_rps > 0, "max_requests_per_second must be positive");

Prevention

When it happens

Trigger: 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.

Common situations: Passing 0-overflowing or sentinel values from config files; unit confusion (requests per minute supplied as per-second); programmatic config generation producing huge numbers.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/10dcf1715cc16e3b. Report an issue: GitHub.