{"record":{"id":"d341c84cbe0c5732","repo":"nautechsystems/nautilus_trader","slug":"invalid-interval-ns-interval-ns-must-be-non-ze","errorCode":null,"errorMessage":"Invalid interval_ns: {interval_ns} (must be non-zero)","messagePattern":"Invalid interval_ns: (.+?) \\(must be non-zero\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/throttler.rs","lineNumber":70,"sourceCode":"/// throttling entirely.\n#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]\n#[serde(deny_unknown_fields)]\npub struct RateLimit {\n    limit: NonZeroUsize,\n    interval_ns: NonZeroU64,\n}\n\nimpl RateLimit {\n    /// Creates a new [`RateLimit`] instance with correctness checking.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if `limit` or `interval_ns` is zero.\n    pub fn new_checked(limit: usize, interval_ns: DurationNanos) -> anyhow::Result<Self> {\n        let limit = NonZeroUsize::new(limit)\n            .ok_or_else(|| anyhow::anyhow!(\"Invalid limit: {limit} (must be non-zero)\"))?;\n        let interval_ns = NonZeroU64::new(interval_ns.as_u64()).ok_or_else(|| {\n            anyhow::anyhow!(\"Invalid interval_ns: {interval_ns} (must be non-zero)\")\n        })?;\n        Ok(Self { limit, interval_ns })\n    }\n\n    /// Creates a new [`RateLimit`] instance.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `limit` or `interval_ns` is zero.\n    #[must_use]\n    pub fn new(limit: usize, interval_ns: DurationNanos) -> Self {\n        Self::new_checked(limit, interval_ns).expect(FAILED)\n    }\n\n    /// Maximum number of messages that can be sent within the interval.\n    #[must_use]\n    pub const fn limit(&self) -> usize {\n        self.limit.get()","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/throttler.rs#L52-L88","documentation":"RateLimit::new_checked validates its inputs before constructing a throttler. This error means interval_ns was 0, which would make the rate-limit window meaningless (division-by-zero / zero-window). The library refuses to construct a RateLimit with a non-zero limit but zero interval.","triggerScenarios":"Calling RateLimit::new_checked(limit, DurationNanos::from(0)) or otherwise passing a zero nanosecond interval while limit is non-zero.","commonSituations":"Config files where an interval field defaults to 0 or is parsed as an empty/placeholder value; computing interval_ns from a frequency or divisor that evaluates to zero; a config migration that dropped the interval value.","solutions":["Pass a positive interval_ns (e.g. DurationNanos for 1s = 1_000_000_000) to new_checked.","Validate/parse the interval from config before construction and reject 0 early with a clear config error.","If the interval is derived, check the derivation (e.g. 1_000_000_000 / rate) cannot produce 0 (rate of 0 or clamped)."],"exampleFix":"// before\nlet rl = RateLimit::new_checked(100, DurationNanos::default())?;\n// after\nlet interval_ns = DurationNanos::from(1_000_000_000); // 1 second\nlet rl = RateLimit::new_checked(100, interval_ns)?;","handlingStrategy":"validation","validationCode":"let interval_ns_u64 = interval_ns.as_u64();\nif limit == 0 || interval_ns_u64 == 0 {\n    return Err(format!(\"limit and interval_ns must be non-zero, got limit={limit}, interval_ns={interval_ns_u64}\"));\n}","typeGuard":null,"tryCatchPattern":"match RateLimit::new_checked(limit, interval_ns) {\n    Ok(rl) => rl,\n    Err(e) => { log::error!(\"rate limit config invalid: {e}\"); return Err(e); }\n}","preventionTips":["Never use DurationNanos::default() (zero) as a real interval.","Validate interval fields at config load time, before construction.","Add unit tests covering zero interval config values."],"tags":["rust","rate-limit","validation","configuration"],"backgroundTag":"invalid-config-value","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"}