nautechsystems/nautilus_trader · error
subscription generation overflow
Error message
subscription generation overflow
What it means
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.
Source
Thrown at crates/adapters/derive/src/data.rs:2008
..Default::default()
};
}
fn clear_transitions(&self) {
self.transitions.clear();
}
}
impl ChannelSubscriptionState {
fn activate(&mut self, owner: ChannelOwner, channel: Option<&str>) -> Option<u64> {
if self.owners.contains_key(&owner) {
return None;
}
self.next_generation = self
.next_generation
.checked_add(1)
.expect("subscription generation overflow");
let generation = self.next_generation;
if let Some(channel) = channel {
self.channels
.entry(channel.to_string())
.or_default()
.insert(owner);
}
self.owners.insert(
owner,
OwnedChannel {
generation,
channel: channel.map(ToOwned::to_owned),
},
);
Some(generation)
}
View on GitHub (pinned to 18893faf8b)
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.
Example fix
// before
self.next_generation = self
.next_generation
.checked_add(1)
.expect("subscription generation overflow");
// after
let Some(next) = self.next_generation.checked_add(1) else {
tracing::error!("subscription generation exhausted; recycling epochs");
return None;
};
self.next_generation = next; Defensive patterns
Strategy: fallback
Validate before calling
let Some(next) = self.next_generation.checked_add(1) else {
return None; // handle exhaustion explicitly
}; Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
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
- DurationNanos overflow in from_micros
- {e}
- MBO delta index overflow
- window index fits u32
- heartbeat request timeout should fit in an instant
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/2f076b1198b27a03.
Report an issue: GitHub.