nautechsystems/nautilus_trader · error

Error dropping role {database}: {e:?}

Error message

Error dropping role {database}: {e:?}

What it means

drop_postgres removes the per-database role after dropping the database. If the DROP ROLE statement fails and the error is not one of the tolerated cases (SQLSTATE 55006 'role is currently in use' / 'current user cannot be dropped'), the function bails with this error, typically because the role still owns objects or other sessions remain connected.

Source

Thrown at crates/infrastructure/src/sql/pg.rs:660

        .execute(pg)
        .await
    {
        Ok(_) => log::info!("Dropped schema public"),
        Err(e) => log::error!("Error dropping schema public: {e:?}"),
    }

    // Drop role
    match sqlx::query(AssertSqlSafe(format!("DROP ROLE IF EXISTS {database};")))
        .execute(pg)
        .await
    {
        Ok(_) => log::info!("Dropped role {database}"),
        Err(e) => {
            let err_msg = e.to_string();
            if err_msg.contains("55006") || err_msg.contains("current user cannot be dropped") {
                log::warn!("Cannot drop currently connected role {database}");
            } else {
                anyhow::bail!("Error dropping role {database}: {e:?}");
            }
        }
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use rstest::rstest;

    use super::*;

    #[rstest]
    fn test_postgres_connect_options_toml_round_trip() {
        let config: PostgresConnectOptions = toml::from_str(
            r#"
host = "localhost"
port = 5432

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the embedded error {e:?} for SQLSTATE: terminate remaining connections first (e.g. SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE usename = '<role>') then retry
  2. Reassign or drop objects owned by the role in other databases (REASSIGN OWNED BY ... / DROP OWNED BY ...) before dropping the role
  3. Ensure you are not connected as the role being dropped; run the drop as a superuser or different admin role
  4. If the tolerated 55006 path was expected, verify no pool or client still holds an open connection before invoking drop_postgres

Example fix

// before: role still owns objects -> bail
"Error dropping role nautilus_trading: DbError { code: \"2BP01\", ... }"
// after
REASSIGN OWNED BY nautilus_trading TO postgres;
DROP OWNED BY nautilus_trading;
DROP ROLE nautilus_trading;
Defensive patterns

Strategy: validation

Validate before calling

// pre-check for active sessions of the role before dropping
SELECT count(*) FROM pg_stat_activity WHERE usename = '<role>';
// pre-check dependent objects
SELECT count(*) FROM pg_class WHERE relowner = 'postgres'::regoper; -- substitute role oid

Try / catch

match drop_postgres(&pool, &database).await {
    Ok(_) => {},
    Err(e) if e.to_string().contains("Error dropping role") => {
        // terminate backends / DROP OWNED, then retry once
        log::warn!("role drop blocked: {e}");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling drop_postgres (via run_database_command drop) when the role still owns objects in other databases (SQLSTATE 2BP01 dependent objects), the role is the current session user, or other active connections hold sessions open with a different error signature.

Common situations: Leftover application connections keeping the role's database in use; the role owning objects in shared databases; running the drop command while connected as the role being dropped; CI environments where a previous test run's pool was not fully closed.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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