nautechsystems/nautilus_trader · error
Position {position_id} not found
Error message
Position {position_id} not found What it means
This panic fires in the cache's bulk position fetch: each position_id in position_ids must exist in self.positions or the code panics via unwrap_or_else. It assumes callers pass only ids of open or retained positions, so a missing id is an invariant violation.
Source
Thrown at crates/common/src/cache/mod.rs:5938
/// Each [`PositionRef`] in the returned vector borrows its underlying cell; mutating any of
/// those positions while the vector is alive will panic at runtime. Drop the vector before
/// issuing writes.
///
/// # Panics
///
/// Panics if any `position_id` in the set is not found in the cache.
fn get_positions_for_ids(
&self,
position_ids: &AHashSet<PositionId>,
side: Option<PositionSide>,
) -> Vec<PositionRef<'_>> {
let mut positions = Vec::new();
for position_id in position_ids {
let position_cell = self
.positions
.get(position_id)
.unwrap_or_else(|| panic!("Position {position_id} not found"));
let position = PositionRef::new(position_cell.borrow());
if side.is_none_or(|side| side == position.side) {
positions.push(position);
}
}
// Sort so callers receive a deterministic Vec across runs; the
// underlying position_ids set is AHash-backed.
positions.sort_by_key(|p| p.id);
positions
}
/// Returns the `ClientOrderId`s of all orders.
#[must_use]
pub fn client_order_ids(
&self,
venue: Option<&Venue>,View on GitHub (pinned to 18893faf8b)
Solutions
- Verify each position_id belongs to the current run and still exists in the cache
- Filter the id list against cache presence before the bulk fetch
- Avoid retaining position ids across cache resets; re-query open positions instead
- Log the missing position_id and cross-check with the originating source
Example fix
// before
let positions = cache.positions(&stale_position_ids, None);
// after
let ids: Vec<PositionId> = stale_position_ids
.into_iter()
.filter(|pid| cache.position(pid).is_some())
.collect();
let positions = cache.positions(&ids, None); Defensive patterns
Strategy: validation
Validate before calling
let known: Vec<&PositionId> = position_ids
.iter()
.filter(|pid| cache.position(pid).is_some())
.collect(); Prevention
- Re-derive open position ids from the cache instead of caching them in strategy state
- Filter against cache presence before bulk fetch
- Clear stored position ids when the cache is reset between runs
When it happens
Trigger: Calling the bulk position accessor with a position_id that was never opened, was closed and purged from the cache, or comes from another backtest/session.
Common situations: Holding position ids from a previous run or report while running a fresh backtest; flat/closed positions removed from the cache but still referenced by strategy state; id typos.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Order {client_order_id} not found
- Order for {} not found to determine position ID
- Order {client_order_id} not found in cache.
- venue-leg quantity calculation validated cumulative fills
- DataActor must be registered before accessing cache
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b1f1bd6c5623f01d.
Report an issue: GitHub.