Skip to content

Conversation

@PouyaPour
Copy link

Problem

When using the RefreshDatabase trait with SQLite in-memory databases, tests can fail with "General error: 1 no such table" errors in subsequent test runs after a PDO connection is detected as closed.

This occurs when:

  1. A test uses database transactions across multiple connections (e.g., mysql and mysql_vandar)
  2. One connection closes or ends its transaction
  3. Laravel detects the connection is not in a transaction and sets RefreshDatabaseState::$migrated = false
  4. The next test triggers re-migration, creating new PDO connections
  5. However, RefreshDatabaseState::$inMemoryConnections still references the old, closed connections
  6. Subsequent tests fail because they're using stale PDO instances without the migrated schema

Root Cause

In RefreshDatabase::refreshTestDatabase(), when RefreshDatabaseState::$migrated is false and migrations run again via migrateDatabases(), the method creates new database connections. However, the stored PDO references in RefreshDatabaseState::$inMemoryConnections are never updated to point to these new connections.

The check in RefreshDatabase::beginDatabaseTransaction():

if ($connection->getPdo() && ! $connection->getPdo()->inTransaction()) {
    RefreshDatabaseState::$migrated = false;
}

Correctly detects when migrations need to run again, but the re-migration process doesn't update the cached in-memory connection references.

Solution

Call updateInMemoryConnections() immediately after migrateDatabases() to ensure RefreshDatabaseState::$inMemoryConnections always references the current, valid PDO instances.

Changes

protected function refreshTestDatabase()
{
    if (! RefreshDatabaseState::$migrated) {
        $this->migrateDatabases();
        $this->app[Kernel::class]->setArtisan(null);
        $this->updateInMemoryConnections(); // Added this line
        RefreshDatabaseState::$migrated = true;
    }

    $this->beginDatabaseTransaction();
}

This ensures that after re-migration, all subsequent tests reference the correct in-memory database connections with the proper schema.

@taylorotwell
Copy link
Member

Can you share a simple reproduction repository?

@taylorotwell taylorotwell marked this pull request as draft November 9, 2025 15:02
@PouyaPour
Copy link
Author

Hi Taylor 👋

Sure! I’ve created a minimal reproduction repository showing the issue:
🔗 https://github.com/PouyaPour/laravel-refreshdatabase-sqlite-bug

Steps To reproduce:**

composer install
cp .env.example .env
php artisan key:generate
php artisan test

Result: Tests 5 and 6 fail with SQLSTATE[HY000]: General error: 1 no such table: users

Key insight: Test 4 passes, but tests 5-6 fail. This happens because:

  1. Test 3 performs a rollback, setting RefreshDatabaseState::$migrated = false
  2. Test 4 triggers re-migration, creating a NEW PDO connection with tables (test passes ✅)
  3. After test 4, beginDatabaseTransaction() calls restoreInMemoryDatabase(), which restores the old, stale PDO from RefreshDatabaseState::$inMemoryConnections (because it was never updated).
  4. Tests 5+ now use the old PDO without any tables (tests fail ❌)

The fix updates $inMemoryConnections after re-migration so restoreInMemoryDatabase() restores the correct PDO reference.

Full explanation in the README. Let me know if you need any clarification!

(And thank you for everything you do for Laravel)

@PouyaPour PouyaPour marked this pull request as ready for review November 10, 2025 05:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants