nautechsystems/nautilus_trader · error
Cannot update position {}: not found in cache
Error message
Cannot update position {}: not found in cache What it means
`update_position` requires the position to already exist in the cache; it mutates the existing shared cell in place. If no position with that ID is held, the method bails instead of creating one — updates are strictly for existing positions (new positions are added via `add_position`).
Source
Thrown at crates/common/src/cache/mod.rs:5433
/// Updates the `order` as pending cancel locally.
pub fn update_order_pending_cancel_local(&mut self, order: &OrderAny) {
self.index
.orders_pending_cancel
.insert(order.client_order_id());
}
/// Updates a `position` already held in the cache.
///
/// Reuses the existing cell so any held [`PositionRef`] handles continue to point at the
/// canonical entry.
///
/// # Errors
///
/// Returns an error if the position is not already held in the cache, or if updating the
/// position in the database fails.
pub fn update_position(&mut self, position: &Position) -> anyhow::Result<()> {
let Some(position_cell) = self.positions.get(&position.id).cloned() else {
anyhow::bail!("Cannot update position {}: not found in cache", position.id);
};
self.refresh_position_indexes(position);
*position_cell.borrow_mut() = position.clone();
if let Some(database) = &mut self.database {
database.update_position(position)?;
// TODO: Implement order snapshots
// if self.snapshot_orders {
// database.snapshot_order_state(order)?;
// }
}
Ok(())
}
/// Updates a cached position by applying an order fill in place.View on GitHub (pinned to 18893faf8b)
Solutions
- Call `add_position` for new positions before any `update_position` call.
- Guard the update with `cache.position(&position.id)` / existence check and add if absent.
- Re-order purge logic so positions are not purged while updates for them are still expected.
Example fix
// before
cache.update_position(&position)?;
// after
if cache.position(&position.id).is_some() {
cache.update_position(&position)?;
} else {
cache.add_position(position.clone());
} Defensive patterns
Strategy: validation
Validate before calling
if cache.position(&position.id).is_none() {
cache.add_position(position.clone()); // or skip update
} else {
cache.update_position(&position)?;
} Prevention
- Check existence before updating positions.
- Sequence purges after all pending updates for a position are done.
- Distinguish add vs update in event-handling code paths.
When it happens
Trigger: Calling `update_position(&position)` for a PositionId never added to the cache, or one already removed/purged (e.g. after `purge_...` of closed positions); passing a position built locally rather than one returned by the cache.
Common situations: Replaying events after the cache was purged of closed positions; restoring state from a snapshot incompletely; constructing a Position in code and trying to 'update' it before any add.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Cannot update position {position_id}: not found in cache
- Cannot persist position with no events: {}
- Active execution intent {intent_id} was not found
- DataActor {} must be registered before calling `cache()` - t
- Order {client_order_id} not found
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f8e7d3977e152fd0.
Report an issue: GitHub.