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

  1. Find and fix any subscribe loop that re-registers subscriptions in a tight cycle — the panic is a symptom, not the cause.
  2. If a larger ID space is needed, widen the generation type (e.g. u128) or recycle generations with an epoch scheme.
  3. In tests, reset or avoid manipulating `next_generation` directly.
  4. 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

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


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