{"record":{"id":"2f076b1198b27a03","repo":"nautechsystems/nautilus_trader","slug":"subscription-generation-overflow","errorCode":null,"errorMessage":"subscription generation overflow","messagePattern":"subscription generation overflow","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/derive/src/data.rs","lineNumber":2008,"sourceCode":"            ..Default::default()\n        };\n    }\n\n    fn clear_transitions(&self) {\n        self.transitions.clear();\n    }\n}\n\nimpl ChannelSubscriptionState {\n    fn activate(&mut self, owner: ChannelOwner, channel: Option<&str>) -> Option<u64> {\n        if self.owners.contains_key(&owner) {\n            return None;\n        }\n\n        self.next_generation = self\n            .next_generation\n            .checked_add(1)\n            .expect(\"subscription generation overflow\");\n        let generation = self.next_generation;\n\n        if let Some(channel) = channel {\n            self.channels\n                .entry(channel.to_string())\n                .or_default()\n                .insert(owner);\n        }\n        self.owners.insert(\n            owner,\n            OwnedChannel {\n                generation,\n                channel: channel.map(ToOwned::to_owned),\n            },\n        );\n        Some(generation)\n    }\n","sourceCodeStart":1990,"sourceCodeEnd":2026,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/derive/src/data.rs#L1990-L2026","documentation":"The Derive adapter versions each subscription with a monotonically increasing `next_generation: u64` counter used by `is_current` to detect stale subscriptions. This panic fires when the counter would wrap past `u64::MAX` (checked_add returns None). It is an astronomically-unlikely overflow guard, not a normal runtime failure.","triggerScenarios":"Calling the subscription-registration function after the process has incremented the generation counter 2^64 times — effectively only reachable via an infinite subscribe/unsubscribe loop or a deliberate test manipulating the counter.","commonSituations":"Essentially never hit in production; appears in fuzz/property tests or when a bug creates a tight loop re-subscribing channels continuously for an impractically long time.","solutions":["Find and fix any subscribe loop that re-registers subscriptions in a tight cycle — the panic is a symptom, not the cause.","If a larger ID space is needed, widen the generation type (e.g. u128) or recycle generations with an epoch scheme.","In tests, reset or avoid manipulating `next_generation` directly.","Keep the checked_add+expect guard; it correctly converts silent wraparound into a loud failure."],"exampleFix":"// before\nself.next_generation = self\n    .next_generation\n    .checked_add(1)\n    .expect(\"subscription generation overflow\");\n// after\nlet Some(next) = self.next_generation.checked_add(1) else {\n    tracing::error!(\"subscription generation exhausted; recycling epochs\");\n    return None;\n};\nself.next_generation = next;","handlingStrategy":"fallback","validationCode":"let Some(next) = self.next_generation.checked_add(1) else {\n    return None; // handle exhaustion explicitly\n};","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid tight subscribe/unsubscribe loops that increment the generation counter","Fix resubscription storms at the application layer","Keep the checked_add guard rather than plain + which wraps silently"],"tags":["rust","panic","overflow","u64"],"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"}