Laravel RefreshDatabase "Migration ... failed" in CI
RefreshDatabase migrates the testing connection at the start of the run. If a migration uses syntax the CI database does not support (common when tests use sqlite but migrations assume MySQL) or references a table created out of order, the whole suite aborts during setup.
What this error means
Tests never run their assertions; setup fails with a QueryException inside a migration, such as "SQLSTATE[HY000]: near ...: syntax error" on sqlite or a foreign key error on a missing table.
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1 no such table: users
(SQL: alter table "posts" add constraint ... foreign key ("user_id"))Common causes
Migrations assume MySQL but tests use sqlite
A migration uses MySQL-only column types or inline DDL that sqlite cannot parse, so RefreshDatabase fails on the testing connection.
A foreign key references a table not yet created
Migration ordering or a dropped table leaves a constraint pointing at a table sqlite has not built, aborting setup.
How to fix it
Run tests against the same engine as production
- Use a MySQL/Postgres service for tests instead of sqlite.
- Point the testing connection at that service.
- Re-run so migrations execute on the engine they were written for.
services:
mysql: { image: mysql:8.0, env: { MYSQL_DATABASE: testing, MYSQL_ROOT_PASSWORD: password }, ports: ['3306:3306'] }Make migrations portable
Split foreign key constraints into a later migration and avoid engine-specific raw DDL so both sqlite and MySQL migrate cleanly.
Schema::table('posts', function (Blueprint $t) {
$t->foreignId('user_id')->constrained();
});How to prevent it
- Test on the same database engine you deploy to.
- Keep migrations portable if you must run sqlite in CI.
- Order foreign keys after the referenced tables exist.