Bali, Indonesia
Insights

Mengira WP_DEBUG Sudah Aktif, Padahal Ditulis di Bawah Baris wp-settings.php

November 4, 2026
0:00
Ada satu anggapan yang sering muncul saat debugging WordPress: selama define( 'WP_DEBUG', true ); sudah ada di wp-config.php, mode debug pasti aktif. Letaknya di mana dianggap tidak penting, toh masih satu file. Kenyataannya, posisi baris itu sangat menentukan. Kalau definisinya ditulis di bawah baris yang memuat wp-settings.php, WordPress sudah selesai menyiapkan dirinya sebelum baris itu sempat dibaca. Hasilnya, debug.log tidak pernah muncul dan error tetap tersembunyi. Pola ini sering terlihat di tiket support. Pengguna menyalin potongan kode dari tutorial, menempelkannya di baris paling bawah wp-config.php karena terasa paling aman, lalu bingung kenapa folder wp-content tetap kosong. Padahal sumber masalahnya ada di urutan eksekusi, bukan di kodenya.
wp-config.php bukan file konfigurasi pasif seperti file .ini yang dibaca utuh lalu diterapkan. File ini adalah skrip PHP biasa yang dieksekusi dari atas ke bawah, baris demi baris. Di bagian akhirnya hampir selalu ada dua hal: penentuan konstanta ABSPATH, lalu require_once ABSPATH . 'wp-settings.php';. Di atasnya biasanya ada komentar penanda semacam "That's all, stop editing!". Teksnya sedikit berbeda antar versi, tapi maksudnya sama. Baris require_once itulah titik baliknya. Begitu wp-settings.php dimuat, WordPress mulai bootstrap, yaitu proses menyiapkan seluruh lingkungannya. Ada dua fungsi di dalamnya yang berkaitan langsung dengan debug. Fungsi pertama adalah wp_initial_constants(). Fungsi ini mengecek konstanta penting dan memberi nilai default untuk yang belum didefinisikan. Polanya kira-kira "kalau WP_DEBUG belum ada, set ke false". Hal yang sama berlaku untuk WP_DEBUG_LOG dan WP_DEBUG_DISPLAY. Fungsi kedua adalah wp_debug_mode(). Fungsi ini membaca nilai konstanta tadi lalu menerapkannya ke PHP: mengatur level error_reporting, menyalakan atau mematikan display_errors, dan kalau WP_DEBUG_LOG aktif, mengarahkan error_log PHP ke wp-content/debug.log. Semua itu terjadi di dalam require_once. Selama wp-settings.php berjalan, WordPress juga memuat plugin, tema, dan seluruh core. Untuk request web biasa, sebagian besar pekerjaan sudah selesai sebelum eksekusi kembali ke baris berikutnya di wp-config.php. Jadi define() yang ditaruh di bawahnya datang terlambat. Keputusan soal debug sudah diambil memakai nilai default false.
Konstanta di PHP hanya bisa didefinisikan sekali. Karena wp_initial_constants() sudah mendefinisikan WP_DEBUG sebagai false, panggilan define( 'WP_DEBUG', true ); berikutnya tidak mengubah apa pun. PHP menolaknya dan mengeluarkan pesan bahwa konstanta sudah didefinisikan. Di PHP 8 pesannya berupa Warning, di versi lama berupa Notice. Ironisnya, pesan itu sendiri biasanya tidak terlihat. Mode debug tidak aktif, jadi pesan tidak tampil di layar dan tidak masuk debug.log. Paling-paling pesan itu tercatat di error log PHP milik server, tergantung pengaturan hosting. Inilah yang membuat masalahnya terasa "diam": tidak ada error, tidak ada file log, dan tidak ada tanda bahwa baris tadi diabaikan. Ada variasi kedua yang efeknya sama dan justru lebih sering terjadi. wp-config.php bawaan biasanya sudah berisi define( 'WP_DEBUG', false ); di bagian tengah file. Lalu seseorang menambahkan define( 'WP_DEBUG', true ); di tempat lain tanpa menghapus yang lama. Di sini aturannya sederhana: definisi pertama yang dieksekusi yang menang. Kalau baris false ada di atas, baris true di bawahnya tidak berpengaruh, bahkan kalau keduanya sama-sama berada di atas wp-settings.php. Satu hal lagi yang sering bikin bingung. Walaupun urutannya sudah benar, debug.log tidak langsung muncul. File itu baru dibuat saat ada sesuatu yang perlu dicatat, misalnya notice, warning, atau error dari PHP. Kalau situs sedang bersih, wajar kalau filenya belum ada. Kemungkinan lain, user PHP tidak punya izin tulis ke folder wp-content, sehingga file tidak pernah bisa dibuat. Jadi sebelum menyimpulkan apa pun, pastikan dulu urutan barisnya benar.
Cara paling cepat adalah melihat nomor baris semua definisi debug dan baris wp-settings.php. Perintah di bawah ini hanya membaca file, jadi aman dijalankan. Jalankan dari folder tempat wp-config.php berada. Biasanya folder itu adalah root instalasi WordPress, tapi file ini juga bisa diletakkan satu level di atasnya.
BASH
grep -nE 'WP_DEBUG|wp-settings' wp-config.php
Contoh format output untuk kasus yang bermasalah, ilustrasi saja dan bukan dari server nyata:
TEXT
82:define( 'WP_DEBUG', false );
96:require_once ABSPATH . 'wp-settings.php';
98:define( 'WP_DEBUG', true );
99:define( 'WP_DEBUG_LOG', true );
Cara membacanya sederhana. Semua baris WP_DEBUG harus punya nomor lebih kecil daripada baris wp-settings.php, dan nama konstanta yang sama tidak boleh muncul lebih dari sekali. Contoh di atas punya dua masalah sekaligus: ada definisi false di baris 82 yang akan menang, dan definisi true di baris 98 sudah terlambat. Hati-hati kalau kamu memakai WP-CLI untuk verifikasi, misalnya lewat wp eval untuk mencetak nilai WP_DEBUG. WP-CLI memuat wp-config.php dengan caranya sendiri. Baris wp-settings.php dipisahkan lalu dimuat terpisah, sehingga define yang letaknya di bawah baris itu bisa tetap terbaca di konteks CLI. Akibatnya, WP-CLI bisa melaporkan true padahal request dari browser tetap memakai false. Untuk kasus ini, grep di atas lebih jujur karena langsung menunjukkan urutan di file. Setelah itu, buktikan lewat request web sungguhan dan lihat apakah debug.log mulai terisi saat halaman yang bermasalah dibuka. Kalau di file tidak ada definisi ganda tapi hasilnya masih aneh, cek juga apakah ada file lain yang ikut di-include di wp-config.php. Beberapa setup memisahkan konfigurasi per environment ke file terpisah. Ada juga panel hosting atau tool manajemen yang menyisipkan baris sendiri. Prinsip urutannya tetap sama: yang dieksekusi lebih dulu yang menang.
Setelah tahu mekanismenya, perbaikannya mudah. Hapus semua definisi lama, lalu taruh satu blok debug tepat di atas komentar "stop editing", jauh sebelum require_once.
PHP
// Satu-satunya blok debug di file ini. Hapus definisi WP_DEBUG lain di atasnya.
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );

/* That's all, stop editing! Happy publishing. */

if ( ! defined( 'ABSPATH' ) ) {
	define( 'ABSPATH', __DIR__ . '/' );
}

require_once ABSPATH . 'wp-settings.php';
WP_DEBUG_DISPLAY diset false supaya error tidak tampil ke pengunjung. Pesan error sering berisi path server, nama tabel, atau potongan query, dan informasi seperti ini tidak perlu terlihat publik. Error tetap tercatat di log. Baris ini_set dipakai sebagai lapisan tambahan, karena beberapa konfigurasi server menyalakan display_errors dari sisi php.ini. Perhatikan juga lokasi log-nya. Secara default, debug.log berada di wp-content. Folder ini ada di dalam document root, sehingga file log bisa saja dibuka langsung dari browser kalau web server tidak memblokirnya. Ada dua cara menutup celah itu. Cara pertama, isi WP_DEBUG_LOG dengan path file di luar folder publik sebagai pengganti true. WordPress versi baru mendukung ini, tapi cek dulu versi yang terpasang. Cara kedua, blokir akses ke file tersebut di level web server. Caranya berbeda antara Apache atau LiteSpeed yang membaca .htaccess dan Nginx yang memakai blok location, jadi sesuaikan dengan stack yang dipakai. Rule of thumb yang aku pegang: mode debug di production adalah alat sementara, bukan pengaturan permanen. Nyalakan secukupnya, reproduksi masalahnya, baca log-nya, lalu matikan lagi. Jangan lupa hapus atau rotasi debug.log. Di situs yang ramai dan penuh notice dari plugin, file ini bisa membesar cukup cepat dan diam-diam memakan kuota disk. Jadi, kalau debug.log tidak kunjung muncul, jangan buru-buru menyalahkan plugin atau izin folder. Buka wp-config.php dan cek urutannya dulu. Pastikan setiap konstanta debug hanya didefinisikan sekali, letaknya di atas require_once ABSPATH . 'wp-settings.php';, dan buktikan hasilnya lewat request web, bukan hanya lewat WP-CLI. Biasanya pengecekan ini cuma butuh satu perintah grep dan hasilnya langsung terlihat.