transact-rs/sqlx · error

failed to apply test fixture {:?}: {:?}

Error message

failed to apply test fixture {:?}: {:?}

What it means

sqlx-core's testing scaffold (setup_test_db, used by #[sqlx::test]) panics when executing a fixture SQL file against the freshly created test database fails. The panic wraps the sqlx error from `conn.execute(fixture.contents)`, printing the fixture path and the underlying DB error, so the real cause (bad SQL, dependency order, missing schema) is in the attached error value.

Source

Thrown at sqlx-core/src/testing/mod.rs:269

    for<'c> &'c mut DB::Connection: Executor<'c, Database = DB>,
{
    let mut conn = copts
        .connect()
        .await
        .expect("failed to connect to test database");

    if let Some(migrator) = args.migrator {
        migrator
            .run_direct(None, &mut conn, false)
            .await
            .expect("failed to apply migrations");
    }

    for fixture in args.fixtures {
        (&mut conn)
            .execute(fixture.contents)
            .await
            .unwrap_or_else(|e| panic!("failed to apply test fixture {:?}: {:?}", fixture.path, e));
    }

    conn.close()
        .await
        .expect("failed to close setup connection");
}

View on GitHub (pinned to 03af8bcc57)

Solutions

  1. Read the wrapped error in the panic message — it names the exact SQL error (relation does not exist, constraint violation, syntax).
  2. Ensure all prerequisite fixtures are listed, dependencies first: `fixtures(path("schema.sql"), path("users.sql"))`.
  3. Run migrations before fixtures (the test scaffold applies migrations if configured; otherwise execute them in a setup step).
  4. Validate the fixture SQL directly: pipe it into a fresh `psql`/`mysql`/`sqlite3` empty database to reproduce outside of tests.
  5. Make fixtures idempotent and self-contained (CREATE TABLE IF NOT EXISTS / ON CONFLICT DO NOTHING).

Example fix

// before
#[sqlx::test(fixtures(path("orders.sql")))]
async fn test_orders(pool: PgPool) { /* orders.sql references users table */ }

// after
#[sqlx::test(fixtures(path("schema.sql"), path("users.sql"), path("orders.sql")))]
async fn test_orders(pool: PgPool) { /* prerequisites loaded first */ }
Defensive patterns

Strategy: validation

Validate before calling

// Validate fixture SQL against a scratch DB before running tests:
// psql "postgres://localhost/scratch" -v ON_ERROR_STOP=1 -f tests/fixtures/orders.sql
// Also list fixtures in dependency order:
// #[sqlx::test(fixtures(path("schema.sql"), path("users.sql"), path("orders.sql")))]

Try / catch

// The panic already embeds the underlying error; parse it in test output:
// failed to apply test fixture "tests/fixtures/orders.sql": <sqlx error> —
// read the wrapped sqlx::Error to find the failing SQL statement.

Prevention

When it happens

Trigger: `#[sqlx::test(fixtures(path("users.sql")))]` where users.sql contains SQL that errors on the empty test database: referencing a table created by another fixture that isn't listed, syntax errors, DB-specific SQL, INSERTs violating constraints, or fixtures executed in the wrong order.

Common situations: Fixture files that worked locally against a manually-seeded dev DB but assume objects a clean test DB lacks; fixture ordering issues (fixtures run in listed order but dependencies not listed first); migrations not applied before fixtures in the test setup.

Related errors


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