nautechsystems/nautilus_trader · error
Venue order ID counter exhausted
Error message
Venue order ID counter exhausted
What it means
The matching engine's venue order ID generator maintains an internal u64/i128-style counter used to build venue order IDs of the form {venue}-{raw_id}-{count}. When incrementing the counter with checked_add overflows the numeric type, generation fails with this error, preventing silent ID reuse or wraparound.
Source
Thrown at crates/execution/src/matching_engine/ids_generator.rs:265
))
}
}
/// Generates a venue order ID.
///
/// # Panics
///
/// Panics if the deterministic order counter is exhausted.
pub fn generate_venue_order_id(&mut self) -> VenueOrderId {
self.try_generate_venue_order_id()
.expect("Venue order ID counter exhausted")
}
fn try_generate_venue_order_id(&mut self) -> anyhow::Result<VenueOrderId> {
self.order_count = self
.order_count
.checked_add(1)
.ok_or_else(|| anyhow::anyhow!("Venue order ID counter exhausted"))?;
if self.use_random_ids {
Ok(VenueOrderId::new(UUID4::new().to_string()))
} else {
Ok(VenueOrderId::new(
format!("{}-{}-{}", self.venue, self.raw_id, self.order_count).as_str(),
))
}
}
}
fn fnv1a_trade_id_hash(venue: Venue, raw_id: u32, ts_init_ns: u64) -> u64 {
let mut hash: u64 = FNV_OFFSET_BASIS;
for bytes in [
venue.as_str().as_bytes(),
b"\x1f",
&raw_id.to_le_bytes(),View on GitHub (pinned to 18893faf8b)
Solutions
- Restart or recreate the matching engine to reset the order ID counter at a safe baseline.
- Enable use_random_ids (UUID-based venue order IDs) so numeric counter capacity is irrelevant.
- Reduce order volume per engine instance or shard the run across multiple engines with distinct raw_id values.
- Upgrade to a build where the counter uses a wider integer type if your workload legitimately exceeds the current width.
Example fix
// before: sequential IDs with huge volume, counter eventually overflows let gen = OrderIdsGenerator::new(venue, raw_id, false /* use_random_ids */); // after: UUID-based IDs avoid counter exhaustion let gen = OrderIdsGenerator::new(venue, raw_id, true /* use_random_ids */);
Defensive patterns
Strategy: validation
Validate before calling
// estimate whether the run can exceed counter capacity before starting
let expected_orders: u128 = estimated_orders(run_config);
assert!(expected_orders < i64::MAX as u128,
"run would exhaust the venue order ID counter; use random IDs or shard"); Try / catch
match ids_generator.get_venue_order_id() {
Err(e) if e.to_string().contains("counter exhausted") => {
log::error!("order ID space exhausted, restarting generator: {e}");
ids_generator.reset(); // or switch to use_random_ids and retry once
}
other => other,
} Prevention
- Prefer use_random_ids for very long-running or high-volume engines.
- Assign distinct raw_id values when sharding across engines.
- Restart engines between backtest runs instead of reusing one instance for billions of orders.
When it happens
Trigger: Generating more venue order IDs in one matching engine's lifetime than the counter type can represent — practically only via extremely long-running simulations, exhaustive backtests, or a misconfigured raw_id base pushing the counter near its maximum.
Common situations: Very large-scale backtests or market-replay runs generating billions of orders; a custom use_random_ids=false setup with a near-max initial raw_id; long-lived live matching engine instances never restarted.
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
- Pending position quantity overflow
- Reduce-only quantity overflow for order {client_order_id}
- Matching engine not found for instrument {order_instrument_i
- Matching engine not found for instrument {instrument_id}
- DurationNanos overflow in from_millis
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/81344ad99e312c28.
Report an issue: GitHub.