Laravel Migration Gagal: Cara Membaca Error SQL

Laravel migration gagal biasanya berarti struktur database yang diminta file migration tidak cocok dengan kondisi database saat ini. Jawaban cepatnya: baca pesan error SQL paling bawah, cek nama tabel/kolom, urutan migration, foreign key, dan koneksi database yang sedang dipakai.

Untuk pemula, error migration sering terlihat seperti masalah Laravel, padahal petunjuk utamanya ada di pesan database seperti Base table or view already exists, Cannot add foreign key constraint, atau Unknown database. Laravel hanya menjalankan instruksi schema; database yang menolak jika instruksinya tidak valid.

Kapan Masalah Ini Biasanya Muncul?

  • php artisan migrate berhenti di tengah jalan
  • tabel tidak terbentuk walaupun file migration sudah ada
  • migration berhasil di laptop teman, tetapi gagal di laptop kamu
  • error muncul setelah mengubah nama tabel atau nama kolom
  • migration gagal saat menambah foreign key
  • test Laravel gagal karena database testing belum sinkron

Penyebab Paling Umum

1. Database Belum Dibuat atau Koneksi Salah

Kalau .env menunjuk ke database yang belum ada, migration tidak bisa berjalan.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=toko_laravel
DB_USERNAME=root
DB_PASSWORD=

Jika database toko_laravel belum dibuat, MySQL bisa mengembalikan error seperti Unknown database.

2. Tabel Sudah Ada

Error seperti ini sering muncul saat kamu pernah membuat tabel manual, lalu menjalankan migration yang membuat tabel dengan nama sama.

SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'produk' already exists

Artinya Laravel mencoba membuat tabel produk, tetapi database sudah punya tabel itu.

3. Urutan Migration Salah

Laravel menjalankan migration berdasarkan timestamp di awal nama file:

2026_05_25_100000_create_kategoris_table.php
2026_05_25_100100_create_produks_table.php

Kalau tabel produks punya foreign key ke kategoris, migration kategoris harus jalan lebih dulu.

4. Nama Tabel atau Kolom Tidak Cocok

Contoh salah:

<?php

Schema::table('produk', function (Blueprint $table) {
    $table->foreignId('category_id')->constrained('categories');
});

Kalau tabel sebenarnya bernama kategoris, constraint ke categories akan gagal.

5. Foreign Key Tidak Cocok Tipe Datanya

Kolom foreign key harus cocok dengan kolom tujuan. Cara paling aman adalah memakai foreignId() dan constrained().

<?php

$table->foreignId('kategori_id')->constrained('kategoris');

Ini lebih aman daripada membuat integer manual lalu menulis foreign key sendiri.

Langkah Diagnosis

  1. Jalankan migration dan baca error paling bawah, bukan hanya baris pertama.
  2. Cek .env: DB_DATABASE, DB_USERNAME, dan DB_PASSWORD.
  3. Jalankan php artisan migrate:status untuk melihat migration mana yang sudah jalan.
  4. Buka file migration terakhir yang gagal.
  5. Bandingkan nama tabel dan kolom dengan schema database yang benar.
  6. Kalau error foreign key, cek apakah tabel tujuan sudah dibuat lebih dulu.
  7. Bersihkan config cache jika baru mengubah .env.
php artisan optimize:clear
php artisan migrate:status
php artisan migrate
Baca Error SQL, Bukan Menebak

Kalau error menyebut 42S01, fokus ke tabel yang sudah ada. Kalau menyebut foreign key, fokus ke urutan tabel, nama tabel tujuan, dan tipe kolom.

Langkah Fix

1. Pastikan Database Ada

Buat database dulu di MySQL sebelum menjalankan migration.

CREATE DATABASE toko_laravel;

Lalu pastikan .env memakai nama yang sama.

2. Kalau Tabel Sudah Ada, Jangan Langsung Hapus Sembarangan

Untuk project belajar yang datanya boleh hilang, kamu bisa reset database:

php artisan migrate:fresh

Kalau ada seeder:

php artisan migrate:fresh --seed

Untuk project yang sudah punya data penting, jangan pakai migrate:fresh. Buat migration baru untuk mengubah struktur tabel.

3. Perbaiki Urutan Migration

Pastikan tabel induk dibuat sebelum tabel anak.

<?php

// create_kategoris_table.php
Schema::create('kategoris', function (Blueprint $table) {
    $table->id();
    $table->string('nama');
    $table->timestamps();
});

// create_produks_table.php
Schema::create('produks', function (Blueprint $table) {
    $table->id();
    $table->foreignId('kategori_id')->constrained('kategoris');
    $table->string('nama');
    $table->timestamps();
});

4. Gunakan Nama Constraint yang Jelas Saat Perlu

Kadang constraint lama masih tersisa saat refactor. Untuk perubahan struktur, buat migration baru yang eksplisit.

<?php

Schema::table('produks', function (Blueprint $table) {
    $table->dropForeign(['kategori_id']);
    $table->foreign('kategori_id')->references('id')->on('kategoris');
});

5. Pisahkan Database Development dan Testing

Jangan sampai test menulis ke database development. Untuk test, pakai database khusus atau SQLite.

DB_CONNECTION=sqlite
DB_DATABASE=:memory:

Contoh Sebelum dan Sesudah

Sebelum

<?php

Schema::create('produks', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('kategori_id');
    $table->foreign('kategori_id')->references('id')->on('kategori');
    $table->timestamps();
});

Masalahnya: tabel tujuan ditulis kategori, padahal migration membuat kategoris.

Sesudah

<?php

Schema::create('produks', function (Blueprint $table) {
    $table->id();
    $table->foreignId('kategori_id')->constrained('kategoris');
    $table->timestamps();
});

Kode lebih pendek dan nama tabel tujuan jelas.

Kesalahan yang Sering Terjadi

Langsung Menjalankan migrate:fresh di Project Berisi Data Penting

migrate:fresh menghapus semua tabel lalu membuat ulang. Aman untuk belajar, berbahaya untuk database yang sudah berisi data penting.

Mengubah File Migration Lama Setelah Sudah Dijalankan

Kalau migration sudah pernah jalan di database lain, lebih aman membuat migration baru untuk perubahan berikutnya.

Lupa Membersihkan Config Cache Setelah Mengubah .env

Laravel bisa masih memakai config lama. Jalankan php artisan optimize:clear setelah mengganti koneksi database.

Membuat Foreign Key Sebelum Tabel Tujuan Ada

Urutan migration penting. Tabel yang direferensikan harus sudah ada lebih dulu.

Pencegahan

  1. Beri nama migration sesuai perubahan yang dilakukan.
  2. Jalankan migrate:status sebelum panik.
  3. Gunakan foreignId()->constrained() untuk relasi sederhana.
  4. Pisahkan database development dan testing.
  5. Jangan edit migration lama yang sudah dipakai banyak environment.

Bacaan Terkait

FAQ

Kenapa migration gagal padahal kode saya terlihat benar?

Kemungkinan kondisi database tidak sama dengan asumsi migration: tabel sudah ada, tabel tujuan foreign key belum ada, atau koneksi database berbeda.

Apakah aman memakai php artisan migrate:fresh?

Aman untuk project belajar atau database lokal yang datanya boleh hilang. Jangan jalankan di production kecuali kamu benar-benar tahu risikonya.

Kenapa setelah mengubah .env, migration masih memakai database lama?

Biasanya config Laravel masih tercache. Jalankan php artisan optimize:clear, lalu ulangi migration.

Apa bedanya migrate, migrate:fresh, dan migrate:refresh?

migrate menjalankan migration yang belum jalan. migrate:fresh menghapus semua tabel lalu menjalankan migration dari awal. migrate:refresh rollback lalu migrate ulang.