transact-rs/sqlx · error

cleanup_test() invoked outside `#[sqlx::test]`

Error message

cleanup_test() invoked outside `#[sqlx::test]`

What it means

Postgres's testing support `cleanup_test` acquires from `MASTER_POOL`, a global pool initialized only inside `#[sqlx::test]`. `.get()` on the uninitialized Option panics with this message when cleanup is called outside the macro's context.

Source

Thrown at sqlx-postgres/src/testing/mod.rs:34

use crate::{PgConnectOptions, PgConnection, Postgres};

pub(crate) use sqlx_core::testing::*;

// Using a blocking `OnceLock` here because the critical sections are short.
static MASTER_POOL: OnceLock<Pool<Postgres>> = OnceLock::new();
// Automatically delete any databases created before the start of the test binary.

impl TestSupport for Postgres {
    fn test_context(
        args: &TestArgs,
    ) -> impl Future<Output = Result<TestContext<Self>, Error>> + Send + '_ {
        test_context(args)
    }

    async fn cleanup_test(db_name: &str) -> Result<(), Error> {
        let mut conn = MASTER_POOL
            .get()
            .expect("cleanup_test() invoked outside `#[sqlx::test]`")
            .acquire()
            .await?;

        do_cleanup(&mut conn, db_name).await
    }

    async fn cleanup_test_dbs() -> Result<Option<usize>, Error> {
        let url = dotenvy::var("DATABASE_URL").expect("DATABASE_URL must be set");

        let mut conn = PgConnection::connect(&url).await?;

        let delete_db_names: Vec<String> = query_scalar("select db_name from _sqlx_test.databases")
            .fetch_all(&mut conn)
            .await?;

        if delete_db_names.is_empty() {
            return Ok(None);
        }

View on GitHub (pinned to 03af8bcc57)

Solutions

  1. Run the test under `#[sqlx::test]` so MASTER_POOL is initialized; let the macro handle cleanup.
  2. Delete explicit `cleanup_test` calls from non-macro tests.
  3. For bespoke cleanup, create your own PgPool from DATABASE_URL and run the cleanup SQL yourself.

Example fix

// before
#[tokio::test]
async fn t() { cleanup_test("mydb").await.unwrap(); }
// after
#[sqlx::test]
async fn t(pool: PgPool) { /* automatic cleanup */ }
Defensive patterns

Strategy: validation

Validate before calling

// cleanup_test requires the #[sqlx::test] context; enforce by convention:
// prefer:
#[sqlx::test]
async fn my_test(pool: sqlx::PgPool) { /* ... */ }
// and delete any manual calls to cleanup_test

Prevention

When it happens

Trigger: Calling the testing API's `cleanup_test(db_name)` from a non-`#[sqlx::test]` test or ordinary async code, so MASTER_POOL was never set.

Common situations: Refactoring tests away from `#[sqlx::test]` while retaining cleanup calls; invoking cleanup in helpers, `Drop` impls, or a separate binary; ordering issues where cleanup runs before any sqlx test initialized the pool.

Related errors


AI-assisted analysis of transact-rs/sqlx@03af8bcc57 (2026-09-03). Data as JSON: /api/errors/8b5a79c1e33e9c65. Report an issue: GitHub.