transact-rs/sqlx · error
cleanup_test() invoked outside `#[sqlx::test]`
Error message
cleanup_test() invoked outside `#[sqlx::test]`
What it means
In MySQL's testing support, `cleanup_test` acquires a connection from `MASTER_POOL`, a lazily-initialized global pool created only by `#[sqlx::test]`. `.get()` on the empty Option panics with this message when cleanup runs outside the macro-managed context.
Source
Thrown at sqlx-mysql/src/testing/mod.rs:32
use sqlx_core::query_scalar::query_scalar;
use sqlx_core::sql_str::AssertSqlSafe;
pub(crate) use sqlx_core::testing::*;
// Using a blocking `OnceLock` here because the critical sections are short.
static MASTER_POOL: OnceLock<Pool<MySql>> = OnceLock::new();
impl TestSupport for MySql {
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 = MySqlConnection::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
- Annotate the test with `#[sqlx::test]` so MASTER_POOL is initialized; drop manual cleanup calls.
- Remove direct `cleanup_test` calls — the macro performs cleanup automatically.
- If you need manual DB cleanup, connect with your own pool via DATABASE_URL instead of the testing API.
Example fix
// before
#[tokio::test]
async fn t() { cleanup_test("mydb").await.unwrap(); }
// after
#[sqlx::test]
async fn t(pool: MySqlPool) { /* cleanup is automatic */ } Defensive patterns
Strategy: validation
Validate before calling
// Only call cleanup inside a #[sqlx::test]; assert initialization first:
// (testing API is internal — guard by convention)
fn ensure_sqlx_test_context() {
// cleanup_test requires MASTER_POOL set by #[sqlx::test]
panic!("do not call cleanup_test outside #[sqlx::test]");
} Prevention
- Use #[sqlx::test] for every test that needs a DB and let it clean up automatically
- Never call testing-module cleanup helpers from #[tokio::test] or application code
- Search the codebase for direct cleanup_test invocations during refactors
When it happens
Trigger: Calling the generated `cleanup_test(db_name)` (or the testing API's cleanup function) directly from a plain `#[tokio::test]` or normal code where no `#[sqlx::test]` has initialized `MASTER_POOL`.
Common situations: Porting tests off `#[sqlx::test]` but keeping cleanup calls; calling cleanup from helpers or drop paths executed outside test context; running tests in a binary that never used the attribute.
Related errors
- DATABASE_URL must be set
- failed to parse DATABASE_URL
- cleanup_test() invoked outside `#[sqlx::test]`
- failed to close setup connection
- DATABASE_URL must be set
AI-assisted analysis of transact-rs/sqlx@03af8bcc57 (2026-09-03).
Data as JSON: /api/errors/aa4346accf8d2f0a.
Report an issue: GitHub.