Fix PHP Fatal error: Maximum function nesting level of '100' reached (Infinite Recursion)

intermediate๐Ÿ˜ PHP2026-05-17| PHP 7.x / 8.x on Linux (Ubuntu, Debian, CentOS), Apache or Nginx + PHP-FPM, with or without Xdebug extension

Error Message

PHP Fatal error: Maximum function nesting level of '100' reached, aborting! in /var/www/html/app.php on line 15
#php#recursion#xdebug#nesting-level#stack-overflow

What just happened?

You called a function, and PHP killed the request with this:

PHP Fatal error: Maximum function nesting level of '100' reached, aborting! in /var/www/html/app.php on line 15

PHP has a built-in safety cap on how deep function calls can nest. When your code recurses too deeply โ€” or when Xdebug lowers that cap โ€” PHP throws this fatal error and stops execution completely. No exceptions are thrown. No try/catch can save you.

Two root causes, different fixes

Before touching anything, figure out which case you're in:

  • Case A: Xdebug is installed and the limit is 100 โ€” Xdebug sets its own nesting limit (default: 100), overriding PHP's native limit. Your code may be perfectly fine โ€” Xdebug just catches it first.
  • Case B: Actual infinite recursion in your code โ€” A function keeps calling itself (or a cycle of functions calls each other) with no exit condition. The limit of 100 is just where PHP gave up.

Step 1 โ€” Check if Xdebug is the trigger

Run this in your terminal:

php -m | grep xdebug

Seeing xdebug in the output means it's loaded. Check its nesting limit:

php -r "echo ini_get('xdebug.max_nesting_level');"

Output of 100 (or any low number)? Xdebug is the culprit โ€” not your code.

Quick fix for Xdebug (development only)

Raise Xdebug's nesting limit in your php.ini or a separate xdebug.ini:

[xdebug]
xdebug.max_nesting_level = 512

Not sure which ini file to edit? Run:

php --ini

Then restart PHP-FPM or Apache:

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

# Apache with mod_php
sudo systemctl restart apache2

512 is enough for legitimate deep recursion โ€” traversing a tree with 200 nested nodes, for example. Don't go to 9999: real infinite recursion will just eat all your memory instead of giving you a clear error.

Step 2 โ€” Find the infinite recursion in your code

No Xdebug, or raising the limit didn't help? You've got actual runaway recursion. Here's how to track it down.

Add a depth counter to suspect functions

Temporarily add a depth guard to any recursive function:

<?php
function processNode(array $node, int $depth = 0): void {
    if ($depth > 50) {
        throw new RuntimeException('Recursion too deep at node: ' . $node['id']);
    }

    // ... your logic ...

    foreach ($node['children'] as $child) {
        processNode($child, $depth + 1);
    }
}

Now you get a real stack trace with the exact node ID causing the cycle โ€” not just a blind fatal error with no context.

Common recursion bugs and their fixes

Bug 1: Missing base case

// BROKEN โ€” no base case
function factorial(int $n): int {
    return $n * factorial($n - 1); // never stops
}

// FIXED
function factorial(int $n): int {
    if ($n  $this->id,
            'parent' => $this->parent->toArray(), // recurses into parent, then its parent...
            'children' => array_map(fn($c) => $c->toArray(), $this->children),
        ];
    }
}

// FIXED โ€” break the cycle by serializing IDs, not full objects
public function toArray(): array {
    return [
        'id' => $this->id,
        'parent_id' => $this->parent->id, // ID only
        'children' => array_map(fn($c) => $c->id, $this->children), // IDs only
    ];
}

Bug 3: Magic method loop (__get / __call)

// __get calling itself indirectly
class Config {
    public function __get(string $key): mixed {
        return $this->$key; // triggers __get again โ†’ infinite loop
    }
}

// FIXED โ€” access the backing store directly
class Config {
    private array $data = [];

    public function __get(string $key): mixed {
        return $this->data[$key] ?? null;
    }
}

Step 3 โ€” Use PHP's call stack to trace the loop

Can't spot the bug just by reading the code? Dump the call stack right before the crash:

<?php
function myRecursiveFunction(array $data): void {
    $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
    if (count($trace) > 8) {
        echo "<pre>";
        debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
        echo "</pre>";
        exit;
    }
    // ... rest of function
}

This prints the last 10 frames before you hit the limit, showing exactly where the cycle started.

Permanent fix: rewrite deep recursion as iteration

In production, the right move is often to ditch recursion entirely. Rewrite the function as a loop with an explicit stack โ€” no nesting limit, no memory surprise on large datasets:

<?php
// Recursive version โ€” hits nesting limit on large trees
function sumTree(array $node): int {
    $total = $node['value'];
    foreach ($node['children'] as $child) {
        $total += sumTree($child);
    }
    return $total;
}

// Iterative version โ€” no recursion limit
function sumTreeIterative(array $root): int {
    $stack = [$root];
    $total = 0;

    while (!empty($stack)) {
        $node = array_pop($stack);
        $total += $node['value'];

        foreach ($node['children'] as $child) {
            $stack[] = $child;
        }
    }

    return $total;
}

Verify the fix worked

  • Reload the page or re-run the failing script.
  • Check your PHP error log โ€” the fatal should be gone:

tail -f /var/log/php/error.log

or for PHP-FPM:

tail -f /var/log/php8.1-fpm.log

  
  - Raised Xdebug's limit? Confirm it took effect:
    ```
php -r "echo ini_get('xdebug.max_nesting_level');"
You should see `512` (or whatever value you set).
  • Rewrote to iteration? Run a quick sanity check with a known input:

$tree = ['value' => 1, 'children' => [ ['value' => 2, 'children' => []], ['value' => 3, 'children' => []], ]]; echo sumTreeIterative($tree); // should print 6

  

## Quick reference

  - **Xdebug installed + limit is 100** โ†’ raise `xdebug.max_nesting_level` in php.ini
  - **No Xdebug, real recursion bug** โ†’ add a depth guard, use `debug_backtrace()` to find the cycle
  - **Production code with deep trees** โ†’ convert recursion to an explicit stack loop
  - **ORM circular references** โ†’ serialize IDs instead of full objects

Related Error Notes