Sửa lỗi 'Fatal error: Maximum function nesting level of 100 reached' trong WordPress

intermediate📝 WordPress2026-05-16| WordPress 5.x–6.x, PHP 7.x–8.x, Xdebug đang bật (môi trường local dev hoặc staging), Linux/Windows/macOS

Error Message

Fatal error: Maximum function nesting level of '100' reached, aborting!
#wordpress#php#xdebug#đệ quy#fatal-error

TL;DR

Chín trên mười trường hợp, lỗi này xuất phát từ Xdebug — không phải code của bạn. Xdebug áp dụng giới hạn lồng nhau mặc định là 100 để phát hiện đệ quy vô hạn. Hãy tăng giá trị này trong php.ini:

; Thêm hoặc cập nhật trong php.ini
xdebug.max_nesting_level = 512

Khởi động lại PHP-FPM hoặc Apache, sau đó tải lại trang. Không dùng Xdebug? Bạn đang gặp lỗi đệ quy thực sự — hãy chuyển đến Fix 4.

Chuyện gì đang xảy ra

PHP không có giới hạn lồng nhau tích hợp sẵn. Thông báo lỗi cụ thể — Fatal error: Maximum function nesting level of '100' reached, aborting! — được chèn hoàn toàn bởi extension Xdebug. Xdebug giới hạn cứng độ sâu lệnh gọi ở mức 100 để ngăn đệ quy vô hạn trước khi nó làm tràn stack của tiến trình PHP.

WordPress tiêu tốn 50–80 lệnh gọi lồng nhau chỉ để tải một trang đơn. Hooks, filters, template includes — chúng chồng chất nhanh chóng. Chỉ cần một plugin thêm vài lớp lệnh gọi, và trên máy dev có Xdebug đang hoạt động, bạn đã vượt giới hạn trước khi trang hoàn tất render.

Các server production hầu như không bao giờ chạy Xdebug. Nếu lỗi này xuất hiện ở môi trường production, đó là lỗi đệ quy thực sự — không phải vấn đề cấu hình.

Fix 1: Tăng giới hạn lồng nhau của Xdebug (phổ biến nhất)

Trước tiên, tìm file php.ini nào đang thực sự được tải:

php --ini
# hoặc:
php -r "echo php_ini_loaded_file();"

Mở file đó và thêm hoặc cập nhật dòng này:

xdebug.max_nesting_level = 512

Sau đó khởi động lại web server:

# Apache
sudo systemctl restart apache2

# Nginx + PHP-FPM
sudo systemctl restart php8.1-fpm

# MAMP / WAMP / Laragon: dùng nút restart trên giao diện đồ họa

512 là giá trị an toàn cho WordPress. Vẫn gặp lỗi ở mức 512? Bạn gần như chắc chắn đang có vòng lặp đệ quy thực sự — không có thay đổi cấu hình nào có thể khắc phục điều đó.

Fix 2: Tắt hoàn toàn Xdebug (nếu bạn không cần dùng ngay)

Xdebug chỉ được cài để debug step thỉnh thoảng? Hãy tắt nó khi không dùng:

# Trên Ubuntu/Debian
sudo phpdismod xdebug
sudo systemctl restart apache2   # hoặc php-fpm

# Hoặc comment out dòng extension trong php.ini:
; zend_extension=xdebug.so

Khi không tải Xdebug, kiểm tra lồng nhau sẽ biến mất hoàn toàn. WordPress tải bình thường.

Fix 3: Override qua .htaccess (phương án dự phòng cho shared hosting)

Không thể chỉnh sửa php.ini trực tiếp? Một số shared host cho phép ghi đè cài đặt PHP qua .htaccess:

# .htaccess (chỉ dành cho Apache)
php_value xdebug.max_nesting_level 512

Một lưu ý: Xdebug đọc giới hạn lồng nhau lúc extension được tải, trước khi bất kỳ code PHP nào chạy. Điều đó có nghĩa là ini_set() trong wp-config.php sẽ không hoạt động — giới hạn đã bị khóa trước đó rồi. Cách dùng .htaccess hoạt động trên một số host, không phải tất cả. Nếu không được, hãy liên hệ host của bạn và yêu cầu họ tăng giới hạn hoặc tắt Xdebug.

Fix 4: Truy tìm đệ quy vô hạn thực sự

Đang chạy trên production không có Xdebug mà vẫn thấy lỗi này? Có gì đó đang đệ quy mất kiểm soát thực sự. Các nguyên nhân thường gặp:

  • Một plugin móc vào một filter và gọi hàm kích hoạt chính filter đó
  • Một shortcode render một shortcode khác, và shortcode kia lại gọi lại cái đầu tiên
  • Một class Walker tùy chỉnh gọi wp_nav_menu() bên trong chính nó
  • Một hàm đệ quy thiếu hoặc không thể đạt được điều kiện dừng

Vô hiệu hóa tất cả plugin cùng lúc để xác nhận nguồn gốc:

# Qua SSH — tạm thời đổi tên thư mục plugins
mv wp-content/plugins wp-content/plugins_backup
mkdir wp-content/plugins

Lỗi biến mất? Bật lại từng plugin một cho đến khi lỗi xuất hiện trở lại. Đó chính là thủ phạm.

Để xác định chính xác vòng lặp bắt đầu từ đâu, thêm backtrace vào hook đáng ngờ:

add_filter('the_content', function($content) {
    debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
    return $content;
}, 5);

Xem output của stack trace. Những tên hàm lặp lại ở cuối call stack chính là nơi đệ quy đang lặp vòng.

Xác nhận fix đã hoạt động

Tải lại trang — nó sẽ hiển thị bình thường. Sau đó xác nhận Xdebug đã nhận giá trị mới từ command line:

php -r "echo ini_get('xdebug.max_nesting_level');"
# Sẽ in ra 512 (hoặc giá trị bạn đã đặt)

Muốn kiểm tra từ bên trong WordPress? Thêm đoạn này vào một file theme tạm thời:

<?php
echo ini_get('xdebug.max_nesting_level');

Vẫn hiển thị 100? Web server của bạn không đọc file php.ini bạn đã chỉnh sửa. CLI, PHP-FPM và Apache module có thể mỗi cái tải một file ini khác nhau. Chạy php --ini trong ngữ cảnh web server của bạn (hoặc kiểm tra phpinfo()) để tìm file nào đang thực sự được sử dụng.

Bảng cheat sheet cho môi trường dev local

  • Lando: thêm xdebug.max_nesting_level: 512 dưới mục config: php: trong .lando.yml, sau đó chạy lando rebuild
  • Valet: chỉnh sửa /usr/local/etc/php/8.x/conf.d/ext-xdebug.ini
  • Docker: đặt biến môi trường XDEBUG_CONFIG=max_nesting_level=512, hoặc mount một file ini tùy chỉnh vào container
  • MAMP: chỉnh sửa trực tiếp /Applications/MAMP/bin/php/phpX.X/conf/php.ini, sau đó khởi động lại MAMP từ giao diện đồ họa

Related Error Notes