Oktober 15, 2026

10 Error Laravel yang Paling Sering Bikin Pusing (dan Cara Memperbaikinya)

Ada momen spesifik yang menandai seorang developer Laravel naik level. Bukan saat dia bisa bikin CRUD dari nol — itu mudah. Tapi saat dia menatap halaman putih kosong bertuliskan "500 Server Error" jam dua pagi, lalu bukannya panik, dia menarik napas dan berkata: "Oke, buka log dulu."

Saya pernah menghabiskan tiga jam begadang karena satu baris yang hilang di file .env. Tiga jam! Kalau waktu itu bisa ditukar pulsa, lumayan buat jajan sebulan. Error Laravel itu menyebalkan bukan karena sulit, tapi karena pesannya sering samar — seperti abang ojek yang cuma bilang "di situ aja, mas", tanpa menjelaskan di situ itu sebelah mana.

Artikel ini saya tulis dari luka lama. Sepuluh error yang hampir pasti pernah (atau akan) kamu temui, lengkap dengan penyebab dan cara memperbaikinya. Bukan teori dari dokumentasi yang dibaca ulang — tapi yang benar-benar terjadi di lapangan, di laptop development, di VPS murah, di jam-jam genting sebelum deadline.

1. 500 Server Error: Halaman Putih Tanpa Dosa

Ini error paling umum sekaligus paling tidak informatif. Browser cuma menampilkan "500 | Server Error" — atau lebih parah, halaman putih polos. Tidak ada petunjuk. Tidak ada jejak. Seperti warung tutup tanpa papan pengumuman.

Kenapa terjadi? Hampir selalu karena APP_DEBUG disetel false. Itu benar di production — kamu tidak mau pengunjung melihat stack trace mentah berisi rahasia aplikasimu. Tapi saat development, ini membuat debugging jadi tebak-tebakan buta. Penyebab sebenarnya bisa apa saja: typo di controller, sintaks PHP rusak, service provider gagal dimuat.

Cara memperbaikinya: pertama, buka file log-nya. Laravel selalu menulis detail error ke storage/logs/laravel.log — selalu. Baris terakhir file itu biasanya adalah jawabannya. Cara tercepat:

tail -n 50 storage/logs/laravel.log

Kalau log-nya kosong atau tidak ada, itu sendiri petunjuk: folder storage mungkin tidak bisa ditulis oleh web server. Perbaiki permission-nya:

chmod -R 775 storage bootstrap/cache

Di environment development, set APP_DEBUG=true di .env supaya error tampil dengan detail (halaman error cantik ala Ignition). Tapi ingat: jangan pernah biarkan true di production. Itu seperti meninggalkan kunci kos di luar pintu.

Pencegahan: biasakan membaca log sebelum panik. Saya sampai punya alias di terminal: alias loglaravel='tail -f storage/logs/laravel.log'. Murah, tapi menyelamatkan banyak malam.

2. "No application encryption key has been specified"

Pesan ini muncul biasanya setelah git clone project orang lain — atau setelah kamu sendiri yang ceroboh menghapus baris APP_KEY di .env. Laravel tidak mau jalan tanpa kunci enkripsi karena session, cookie terenkripsi, dan password reset semuanya bergantung padanya.

Solusinya satu baris, dan ini yang paling memuaskan di daftar ini:

php artisan key:generate

Perintah itu membuat kunci acak dan menuliskannya ke APP_KEY di .env. Selesai. Error hilang.

Tapi tunggu — kalau kamu dapat error ini di server production, jangan asal generate ulang. Data yang terenkripsi dengan kunci lama (session aktif, cookie "remember me", token reset password) akan jadi tidak terbaca dengan kunci baru. User yang sedang login akan tiba-tiba logout massal. Generate kunci sekali, simpan baik-baik, dan jangan pernah menggantinya tanpa rencana.

Pencegahan: pastikan file .env.example di repo-mu berisi APP_KEY= (kosong) dengan komentar yang jelas, dan tim-mu tahu langkah setup-nya. Satu baris dokumentasi di README bisa menghemat satu jam kebingungan.

3. SQLSTATE[HY000] [2002] Connection refused — Favorit Saya

Error nomor tiga ini favorit saya. Bukan karena saya suka — justru karena ia muncul di momen paling dramatis: semua kode sudah benar, migration sudah rapi, tiba-tiba aplikasi melempar "SQLSTATE[HY000] [2002] Connection refused". Rasanya seperti masakan sudah matang, tapi kompornya ternyata mati.

Terjemahan bebasnya: PHP tidak bisa menghubungi database. Titik. Penyebabnya hampir selalu salah satu dari tiga:

  • MySQL/MariaDB belum jalan. Di laptop, pastikan servicenya running. Di XAMPP/Laragon, cek panelnya. Di VPS, systemctl status mysql (atau mariadb).
  • Konfigurasi .env salah. Cek DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD. Kesalahan klasik: DB_HOST=127.0.0.1 vs localhost — keduanya bisa berperilaku beda tergantung setup socket MySQL. Kalau satu tidak bisa, coba yang lain.
  • Database-nya belum dibuat. Laravel tidak membuat database untukmu — php artisan migrate mengisi tabel, bukan membuat database. Buat dulu manual: CREATE DATABASE nama_db;

Cara diagnosis tercepat: coba konek manual dari terminal.

mysql -h 127.0.0.1 -u root -p

Kalau perintah itu saja gagal, masalahnya di server database — bukan di Laravel. Jangan utak-atik kode sebelum langkah ini.

Pencegahan: setelah clone project baru, urutan sakral saya selalu sama: buat database dulu → isi .env → baru migrate. Urutan ini tidak pernah mengecewakan.

4. "Target class [XController] does not exist"

Error ini adalah jebakan migrasi versi. Kalau kamu belajar dari tutorial Laravel 7 ke bawah, atau memindahkan kode lama ke project baru, kamu akan menemukannya: route seperti Route::get('/user', 'UserController@index'); tiba-tiba ditolak dengan pesan "Target class [UserController] does not exist".

Sejak Laravel 8, route tidak lagi otomatis diberi prefix namespace App\Http\Controllers. Dulu framework yang menebak namespace-nya; sekarang kamu harus menyebutkannya eksplisit.

Solusi modern (cara yang benar):

use App\Http\Controllers\UserController;  Route::get('/user', [UserController::class, 'index']);

Atau kalau kamu sedang memindahkan project lama dan tidak mau mengubah ratusan route, ada jalan pintas: aktifkan kembali prefix namespace lama di app/Providers/RouteServiceProvider.php dengan menambahkan protected $namespace = 'App\\Http\\Controllers';. Tapi jujur? Itu menunda masalah. Lebih baik sekalian migrasi ke sintaks baru — cuma sekali sakitnya.

Pelajaran: kalau mengikuti tutorial, cek versi Laravel yang dipakai tutorial itu. Tutorial 2020 untuk Laravel 11 adalah resep kekacauan.

5. 419 Page Expired: Token CSRF yang Hilang

Kamu isi form pendaftaran dengan khusyuk. Nama, email, password — semua benar. Klik "Daftar". Lalu muncul: "419 Page Expired". Rasanya seperti sudah antre panjang di kasir, lalu kasirnya bilang strukmu kedaluwarsa.

Laravel melindungi semua form POST dari serangan CSRF (Cross-Site Request Forgery) dengan token tersembunyi. Kalau token itu tidak ada atau sudah kedaluwarsa, request ditolak mentah-mentah — demi keamananmu sendiri, sebenarnya.

Solusi 90% kasus: tambahkan direktif @csrf di dalam tag <form>:

<form method="POST" action="/daftar">     @csrf     <input type="email" name="email" placeholder="[email protected]">     <button type="submit">Daftar</button> </form>

Direktif itu me-render satu input hidden berisi token. Tanpa dia, Laravel menganggap request-mu mencurigakan.

Kasus 10% lainnya: session kedaluwarsa. Kalau form dibiarkan terbuka berjam-jam (tab yang ditinggal tidur siang, misalnya), token di session sudah tidak valid. Refresh halaman, isi ulang, kirim lagi. Dan kalau kamu mengirim request via AJAX/fetch, jangan lupa sertakan token di header X-CSRF-TOKEN — biasanya diambil dari meta tag csrf-token di layout.

6. Class Not Found: Perang Case-Sensitivity yang Sunyi

"Class 'App\Models\user' not found" — padahal file-nya jelas ada di app/Models/User.php. Kamu lihat foldernya, file-nya ada. Tapi Laravel bersikeras tidak menemukannya. Ini error yang membuat orang mempertanyakan kewarasannya sendiri.

Ada dua tersangka utama:

Tersangka pertama: autoload belum di-refresh. Setiap kali menambah class baru (terutama di luar konvensi), jalankan:

composer dump-autoload

Perintah ini membangun ulang peta class Composer. Murah, cepat, dan menyelesaikan sebagian besar kasus.

Tersangka kedua — dan ini yang licik: case-sensitivity. Di Windows dan macOS, User.php dan user.php dianggap file yang sama. Di Linux (baca: server production-mu), keduanya beda. Jadi kode yang jalan sempurna di laptop Windows bisa meledak di VPS Ubuntu hanya karena satu huruf kapital. PSR-4 menuntut nama class persis sama dengan nama file, termasuk kapitalisasinya.

Saya pernah debugging ini satu jam penuh, hanya untuk menemukan folder bernama models (huruf kecil) di project yang di-clone dari laptop teman. Satu huruf. Satu jam. Pelajaran mahal yang tidak akan saya lupakan.

Pencegahan: kembangkan di environment yang mirip production (Docker atau WSL), dan aktifkan linter/IDE yang memperingatkan inkonsistensi nama class. Atau paling tidak, biasakan dump-autoload setiap kali ada class baru.

7. Gambar 404 Setelah Upload: Storage Link yang Terlupakan

Upload berhasil. File-nya ada di storage/app/public/foto.jpg. Tapi browser menampilkan 404 saat mengakses /storage/foto.jpg. Gambar hantu — ada tapi tidak terlihat.

Penjelasannya sederhana: folder public/ adalah satu-satunya yang bisa diakses browser, sedangkan storage/ sengaja disembunyikan. Laravel menjembatani keduanya dengan symbolic link dari public/storage ke storage/app/public. Link itu tidak dibuat otomatis.

Solusinya:

php artisan storage:link

Satu perintah, link tercipta, gambar muncul. Tapi ada catatan penting untuk production: kalau kamu deploy dengan cara menghapus seluruh folder lalu mengunggah ulang (bukan git pull), symlink itu ikut terhapus — dan harus dibuat ulang setiap deploy. Masukkan storage:link ke script deploy-mu, atau kamu akan mengulangi error ini setiap rilis. Percayalah, saya tahu dari pengalaman.

Dan kalau upload di server shared hosting yang tidak mengizinkan symlink? Simpan file langsung ke disk public (konfigurasi filesystems.php), atau pindah ke object storage. Jangan memaksa symlink di tempat yang melarangnya.

8. Composer: "Allowed memory size exhausted"

Ini bukan error Laravel, tapi error ini yang paling sering menghalangi orang memasang Laravel. Kamu jalankan composer install, progress bar berjalan manis, lalu: "Fatal error: Allowed memory size of 1610612736 bytes exhausted". Composer kehabisan memori saat menyelesaikan dependency — terutama di VPS RAM 1 GB atau laptop kentang.

Solusi cepat:

COMPOSER_MEMORY_LIMIT=-1 composer install

Environment variable itu memberi tahu Composer untuk mengabaikan batas memori PHP. Nilai -1 artinya tanpa batas — Composer boleh memakai memori sebanyak yang ia butuhkan.

Solusi permanen (lebih rapi): naikkan memory_limit di php.ini khusus CLI, atau set variable itu di ~/.bashrc supaya tidak perlu diketik setiap kali. Alternatif lain: jalankan composer update dengan flag --no-dev di production — dependency lebih sedikit, memori yang dibutuhkan lebih kecil, dan memang itulah yang seharusnya di server production.

Catatan jujur: kalau VPS-mu RAM-nya 512 MB dan Composer tetap gagal, itu bukan salah Composer — itu tanda sudah waktunya upgrade paket VPS. Jangan menyiksa diri.

9. Migration Gagal: SQLSTATE[42S01] Table Already Exists

Kamu jalankan php artisan migrate dan Laravel protes: tabel users sudah ada. Padahal tabel migrations (catatan migration yang sudah jalan) tidak mencatatnya. Ini biasanya akibat migration yang gagal di tengah jalan: tabel terlanjur dibuat, tapi catatannya tidak tersimpan.

Cara membereskannya: pertama, lihat kondisi sebenarnya.

php artisan migrate:status

Perintah ini menampilkan daftar migration dan statusnya (sudah jalan atau belum). Lalu pilih salah satu:

  • Kalau tabelnya memang sampah/percobaan: hapus tabelnya manual dari database (DROP TABLE users;), lalu migrate ulang. Bersih dan cepat.
  • Kalau tabelnya berisi data penting: jangan di-drop! Tandai migration-nya sebagai sudah jalan tanpa mengeksekusinya. Cara paling aman: tambahkan barisnya manual ke tabel migrations, atau tulis ulang migration-nya dengan Schema::table alih-alih Schema::create.

Pencegahan yang sebenarnya: tulis migration yang reversible. Method down() jangan dikosongkan — isi dengan kebalikan dari up(). Dan untuk operasi berisiko, bungkus dalam transaction atau gunakan --step saat migrate supaya kegagalan mudah di-rollback satu per satu. Migration yang baik itu seperti memanjat dengan tali pengaman: kamu berharap tidak jatuh, tapi talinya tetap dipasang.

10. .env Tidak Terbaca: Cache Config yang Bandel

Error terakhir ini bukan error dengan pesan dramatis — justru sebaliknya, ia menyamar. Kamu ubah APP_NAME di .env, refresh browser, dan... tidak berubah. Kamu ubah kredensial database, tetap konek ke database lama. Seolah-olah .env-mu diabaikan. Rasanya seperti ngomong ke tembok.

Tersangkanya: config cache. Seseorang (mungkin kamu sendiri, mungkin tutorial yang kamu ikuti) pernah menjalankan php artisan config:cache. Sejak itu Laravel membaca konfigurasi dari file cache, bukan dari .env — perubahan .env apa pun tidak akan berpengaruh sampai cache dihapus.

Solusinya — paket kombo pembersih cache:

php artisan config:clear php artisan cache:clear php artisan route:clear php artisan view:clear

Aturan mainnya jelas: jangan pernah config:cache saat development — itu sumber 90% kebingungan "kok tidak berubah". Perintah cache (config:cache, route:cache, view:cache) hanya untuk production, dijalankan sebagai bagian dari script deploy setelah .env final terisi. Di laptop? Biarkan Laravel membaca .env secara live. Sedikit lebih lambat, jauh lebih waras.

Penutup: Debugging Itu Keterampilan, Bukan Bakat

Kalau ada satu benang merah dari sepuluh error di atas, ini dia: baca log sebelum panik. Hampir semua error Laravel meninggalkan jejak yang jelas di storage/logs/laravel.log — lengkap dengan file, baris, dan stack trace. Kebiasaan membuka log terlebih dahulu akan memangkas waktu debugging-mu dari hitungan jam jadi hitungan menit.

Alur sistematis yang saya pakai sampai hari ini, dan tidak pernah mengecewakan:

  1. Baca pesan error-nya — benar-benar baca, jangan cuma lihat angkanya. Laravel (terutama dengan Ignition di mode debug) biasanya sudah memberi tahu file dan baris penyebabnya.
  2. Cek log — tail -f storage/logs/laravel.log sambil mereproduksi error. Stack trace tidak berbohong.
  3. Isolasi — komentari bagian yang dicurigai, atau reproduksi di route paling sederhana. Kalau error hilang saat satu bagian dimatikan, pelakunya ketemu.
  4. Verifikasi asumsi — konek database manual, cek permission folder, pastikan .env terbaca. Jangan menebak; buktikan.
  5. Baru cari di internet — dengan pesan error yang spesifik, bukan "laravel error help". Stack Overflow jauh lebih membantu kalau kamu datang dengan baris log yang tepat.

Dan kalau project-mu sudah cukup besar sampai error-errornya sulit dilacak manual, saatnya berkenalan dengan Laravel Telescope — toolbar debug resmi Laravel yang mencatat request, query database, log, dan exception dalam satu dasbor. Install-nya gampang (composer require laravel/telescope --dev lalu php artisan telescope:install), dan ia mengubah debugging dari "mencari jarum di tumpukan jerami" jadi "membuka laci yang berlabel". Untuk project serius, ini investasi yang sepadan.

Sepuluh error di atas bukan daftar untuk dihafal — mereka pola untuk dikenali. Semakin sering kamu menemukannya (dan kamu akan menemukannya), semakin cepat jarimu mengetik solusinya tanpa berpikir. Begadang karena error memang tidak bisa dihindari sepenuhnya. Tapi begadang tiga jam untuk satu baris .env? Itu, semoga, cukup sekali seumur hidup.

Tim Redaksi TnError

Media teknologi berbahasa Indonesia — meliput keamanan siber, tutorial praktis, dan kabar teknologi terkini dengan verifikasi berlapis sebelum terbit.