nautechsystems/nautilus_trader · error

delete_position not implemented for PostgreSQL cache adapter

Error message

delete_position not implemented for PostgreSQL cache adapter: {position_id}

What it means

Sentinel error in the PostgreSQL cache adapter's delete_position: position deletion is not implemented for the PostgreSQL cache backend, so the operation always fails and reports the position ID involved.

Source

Thrown at crates/infrastructure/src/sql/cache.rs:897

        todo!()
    }

    fn load_strategy(&self, strategy_id: &StrategyId) -> anyhow::Result<AHashMap<String, Bytes>> {
        anyhow::bail!("load_strategy not implemented for PostgreSQL cache adapter: {strategy_id}")
    }

    fn delete_strategy(&self, _strategy_id: &StrategyId) -> anyhow::Result<()> {
        todo!()
    }

    fn delete_order(&self, client_order_id: &ClientOrderId) -> anyhow::Result<()> {
        anyhow::bail!(
            "delete_order not implemented for PostgreSQL cache adapter: {client_order_id}"
        )
    }

    fn delete_position(&self, position_id: &PositionId) -> anyhow::Result<()> {
        anyhow::bail!("delete_position not implemented for PostgreSQL cache adapter: {position_id}")
    }

    fn delete_account_event(&self, account_id: &AccountId, event_id: &str) -> anyhow::Result<()> {
        anyhow::bail!(
            "delete_account_event not implemented for PostgreSQL cache adapter: {account_id}, {event_id}"
        )
    }

    fn add(&self, key: String, value: Bytes) -> anyhow::Result<()> {
        let query = DatabaseQuery::Add(key, value.into());
        self.tx
            .send(query)
            .map_err(|e| anyhow::anyhow!("Failed to send query to database message handler: {e}"))
    }

    fn add_currency(&self, currency: &Currency) -> anyhow::Result<()> {
        let query = DatabaseQuery::AddCurrency(*currency);
        self.tx.send(query).map_err(|e| {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Avoid deleting positions on the SQL adapter; query/filter closed positions instead of removing them
  2. Use the Redis adapter where position deletion is needed
  3. Implement delete_position in sql/cache.rs with the corresponding SQL DELETE

Example fix

// before
cache_db.delete_position(&position_id)?; // bails on Postgres
// after
let result = cache_db.delete_position(&position_id);
if let Err(e) = result { log::warn!("delete_position unsupported: {e}"); }
Defensive patterns

Strategy: try-catch

Validate before calling

if is_postgres_cache(&cache_db) { /* deletion unsupported — skip */ }

Type guard

fn is_postgres_cache(db: &dyn CacheDatabase) -> bool { db.as_any().downcast_ref::<PostgresCache>().is_some() }

Try / catch

if let Err(e) = cache_db.delete_position(&position_id) {
    if e.to_string().contains("not implemented") {
        log::debug!("position retained in SQL cache (delete unsupported)");
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: Calling cache.delete_position for a PositionId with the PostgreSQL cache adapter — e.g. purging closed positions or cleanup tooling.

Common situations: Maintenance jobs ported from the Redis adapter; freeing storage of historical closed positions; test teardown on a shared Postgres cache.

Related errors


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