147

I have made a function that finds all the URLs within an html file and repeats the same process for each html content linked to the discovered URLs. The function is recursive and can go on endlessly. However, I have put a limit on the recursion by setting a global variable which causes the recursion to stop after 100 recursions.

However, php returns this error:

Fatal error: Maximum function nesting level of '100' reached, aborting! in D:\wamp\www\crawler1\simplehtmldom_1_5\simple_html_dom.php on line 1355

ERROR

I found a solution here: Increasing nesting function calls limit but this is not working in my case.

I am quoting one of the answers from the link mentioned above. Please do consider it.

"Do you have Zend, IonCube, or xDebug installed? If so, that is probably where you are getting this error from.

I ran into this a few years ago, and it ended up being Zend putting that limit there, not PHP. Of course removing it will let >you go past the 100 iterations, but you will eventually hit the memory limits."

Is there a way to increase the maximum function nesting level in PHP

Community
  • 1
  • 1
Rafay
  • 6,108
  • 11
  • 51
  • 71
  • 2
    Also: PHP doesn't have a limit on nested function calls, it must be an extension you're using that causes this. – Abel Dec 28 '11 at 12:57
  • @Abel I am sure that my code has no errors. There is a static variable which increments its value by one on each recursive call. If that variable is less than 100, the recursive calls go on until the variable reaches 100. I mean to say that the variable reaching 100 is actually the base case. While the error arises before 100 recursions. And as you have mentioned that some extension my be causing this, I would like to mention that I am using functions from simple_html_dom.php. If you have any idea about simple_html_dom.php, please help me in this regard. Please refer to updated question. – Rafay Dec 28 '11 at 13:13
  • 7
    That is an error by xdebug. From the screenshot it's visible you use xdebug. You can disable the setting here: [xdebug.max_nesting_level](http://xdebug.org/docs/basic) or tell how large the nesting level is. – hakre Jun 02 '12 at 13:52
  • 3
    if use WAMP, note that disabling xdebug in php.ini does NOT always work; same applies to extending level of allowed nesting; a bug a guess; SOLUTION: go to php.ini and comment out php_xdebug-???.dll – Jeffz May 10 '13 at 10:37
  • Possible duplicate of [Increasing nesting functions calls limit](http://stackoverflow.com/questions/4293775/increasing-nesting-functions-calls-limit) – A.L Nov 19 '15 at 17:20
  • I just ran into this using a recursive algorithm on a large data set. No value for max_nesting_level is large enough in my case and I had to find a non-recursive method to do the same thing. It took longer, but it ran to completion. – Brian Mar 29 '18 at 06:26

23 Answers23

160

Increase the value of xdebug.max_nesting_level in your php.ini

Mohammad
  • 21,175
  • 15
  • 55
  • 84
Maxence
  • 12,868
  • 5
  • 57
  • 69
62

A simple solution solved my problem. I just commented this line:

zend_extension = "d:/wamp/bin/php/php5.3.8/zend_ext/php_xdebug-2.1.2-5.3-vc9.dll

in my php.ini file. This extension was limiting the stack to 100 so I disabled it. The recursive function is now working as anticipated.

Bram
  • 2,515
  • 6
  • 36
  • 58
Rafay
  • 6,108
  • 11
  • 51
  • 71
  • 4
    So, eventually it was the XDebug extension after all... Good to know. In two days you can accept your own answer as accepted answer, if you want (and have a look at your previous questions, most miss an accepted answer). – Abel Dec 29 '11 at 14:47
  • 68
    Dealing with the excessive recursion is surely better than just turning off the monitoring. – petesiss Aug 30 '12 at 13:50
  • 7
    That's a heavy-handed approach. The above answers that mention the variable to adjust the max stack depth is a better approach. – aredridel Dec 04 '12 at 14:43
  • I agree it is heavy handed and depending on your situation it may be better to fix the problem first, however on a broken site this answer will fix it and then allow you to debug the problem using the other answers. – DrCord Aug 02 '13 at 17:55
  • 7
    You shold not have xdebug enabled in a production environment. – HarryFink Dec 02 '13 at 10:04
  • 1
    This solution is too drastic, if you depend on Xdebug to debug the source code is not a good option. Not advisable that solution unless it is just a test – vandersondf Jul 23 '15 at 18:46
  • Wrong: You did not solve the problem, you have just hidden the symptom. – Sebastian Mach Jan 28 '16 at 11:56
  • 4
    holy crap. I can't stop laughing at the chosen solution. So my PC wouldn't stop making noise, so I found the solution. Turn it off. :) – Kevin Remisoski May 01 '17 at 04:05
45

Another solution is to add xdebug.max_nesting_level = 200 in your php.ini

bacar ndiaye
  • 595
  • 4
  • 4
  • 10
    it's also possible to do it in php, for example in the config file of your project. ```ini_set('xdebug.max_nesting_level', 200); ``` – svassr May 25 '14 at 15:23
  • @htxryan I'm not an expert but it's due to your call stack being too "deep" (too many functions calling other functions). The typical scenario where this occurs is with a recursive function. The setting is most likely there to avoid "out of control" recursion due to a bug in the code. – Bryan Oct 16 '15 at 00:46
  • @svassr you might want to consider adding that tip as a separate answer or adding to an existing one, it was helpful to me but almost missed it in the comments – Bryan Oct 16 '15 at 13:52
  • @Bryan just added an answer – svassr Oct 19 '15 at 15:09
43

Rather than going for a recursive function calls, work with a queue model to flatten the structure.

$queue = array('http://example.com/first/url');
while (count($queue)) {
    $url = array_shift($queue);

    $queue = array_merge($queue, find_urls($url));
}

function find_urls($url)
{
    $urls = array();

    // Some logic filling the variable

    return $urls;
}

There are different ways to handle it. You can keep track of more information if you need some insight about the origin or paths traversed. There are also distributed queues that can work off a similar model.

Louis-Philippe Huberdeau
  • 5,341
  • 1
  • 19
  • 22
23

Rather than disabling the xdebug, you can set the higher limit like

xdebug.max_nesting_level=500

shahinam
  • 680
  • 5
  • 6
  • @SebastianMach: and, amazingly, years after, too. :) (Like four more times, or so. People not only don't read now, they don't even scroll any more.) – Sz. Feb 23 '17 at 16:27
  • 1
    @Sz.: Wow, what a blast from the past :P Amazingly shocking. – Sebastian Mach Feb 25 '17 at 11:35
20

It's also possible to fix this directly in php, for example in the config file of your project.

ini_set('xdebug.max_nesting_level', 200);

svassr
  • 5,538
  • 5
  • 44
  • 63
  • 1
    Thanks, this works nicely as I don't have to worry about updating php.ini on all my dev boxes, I just add this to my application's bootstrap file. – Bryan Oct 19 '15 at 15:45
  • This is the best solution when working with multiple dev environments! Thanks – Owen Far Nov 10 '20 at 10:51
13

Go into your php.ini configuration file and change the following line:

xdebug.max_nesting_level=100

to something like:

xdebug.max_nesting_level=200
13

on Ubuntu using PHP 5.59 :
got to `:

/etc/php5/cli/conf.d

and find your xdebug.ini in that dir, in my case is 20-xdebug.ini

and add this line `

xdebug.max_nesting_level = 200


or this

xdebug.max_nesting_level = -1

set it to -1 and you dont have to worry change the value of the nesting level.

`

Gujarat Santana
  • 9,854
  • 17
  • 53
  • 75
12

probably happened because of xdebug.

Try commenting the following line in your "php.ini" and restart your server to reload PHP.

  ";xdebug.max_nesting_level"

e-sushi
  • 13,786
  • 10
  • 38
  • 57
vandersondf
  • 839
  • 1
  • 9
  • 8
  • 2
    or disabled all xdebug – zloctb Oct 04 '13 at 05:53
  • 2
    How would this work? If you don't manually define the limit, it will just revert to the default, which is 100 (http://xdebug.org/docs/basic). By commenting this line out, all you do it force the setting to revert to the default. – justanotherprogrammer Dec 10 '13 at 15:47
  • Disable all xdebug is not recommended if you depend his use of tool; Normally the configuration "xdebug.max_nesting_level" is used without know his real use, so generally only comment is enough and valid. – vandersondf Jul 25 '18 at 12:46
12

Try looking in /etc/php5/conf.d/ to see if there is a file called xdebug.ini

max_nesting_level is 100 by default

If it is not set in that file add:

xdebug.max_nesting_level=300

to the end of the list so it looks like this

xdebug.remote_enable=on
xdebug.remote_handler=dbgp
xdebug.remote_host=localhost
xdebug.remote_port=9000
xdebug.profiler_enable=0
xdebug.profiler_enable_trigger=1
xdebug.profiler_output_dir=/home/drupalpro/websites/logs/profiler
xdebug.max_nesting_level=300

you can then use @Andrey's test before and after making this change to see if worked.

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'
Community
  • 1
  • 1
Lee Woodman
  • 1,319
  • 2
  • 16
  • 30
  • Great, the first answer that mentions that xdebug has a separate `.ini` file. By the way when you run php5-fpm this file is probably somewhere here: `/etc/php5/fpm/conf.d/20-xdebug.ini` – Daan Sep 08 '16 at 10:21
8

php.ini:

xdebug.max_nesting_level = -1

I'm not entirely sure if the value will ever overflow and reach -1, but it'll either never reach -1, or it'll set the max_nesting_level pretty high.

Martyn Shutt
  • 1,671
  • 18
  • 25
  • 1
    It works! No matter if you use XDebug or not, neither if you comment out line in php.ini. I explicitly used: ini_set('xdebug.max_nesting_level', -1); – user2928048 May 09 '16 at 14:16
6

Check recursion from command line:

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'

if result > 100 THEN check memory limit;

Christian Giupponi
  • 7,408
  • 11
  • 68
  • 113
Andrey
  • 307
  • 4
  • 5
6

You could convert your recursive code into an iterative code, which simulates the recursion. This means that you have to push the current status (url, document, position in document etc.) into an array, when you reach a link, and pop it out of the array, when this link has finished.

Yogu
  • 9,165
  • 5
  • 37
  • 58
5
<?php
ini_set('xdebug.max_nesting_level', 9999);
... your code ...

P.S. Change 9999 to any number you want.

cofirazak
  • 562
  • 6
  • 16
5

You could try to wiggle down the nesting by implementing parallel workers (like in cluster computing) instead of increasing the number of nesting function calls.

For example: you define a limited number of slots (eg. 100) and monitor the number of "workers" assigned to each/some of them. If any slots become free, you put the waiting workers "in them".

tamasgal
  • 24,826
  • 18
  • 96
  • 135
  • 1
    That's not really a generally applicable approach. That's more sensible to parallelize, not avoid stack depth. – aredridel Dec 04 '12 at 14:42
4

Stumbled upon this bug as well during development.

However, in my case it was caused by an underlying loop of functions calling eachother - as a result of continuous iterations during development.

For future reference by search engines - the exact error my logs provided me with was:

Exception: Maximum function nesting level of '256' reached, aborting!

If, like in my case, the given answers do not solve your problem, make sure you're not accidentally doing something along the lines of the following simplified situation:

function foo(){
    // Do something
    bar();
}

function bar(){
    // Do something else
    foo();
}

In this case, even if you set ini_set('xdebug.max_nesting_level', 9999); it will still print out the same error message in your logs.

Kay Angevare
  • 639
  • 6
  • 17
3

If you're using Laravel, do

composer update

This should be work.

  • You should add more background information about this. This could be useful though https://laracasts.com/forum/?p=2309-fatal-error-tests-not-finished-maximum-function-nesting-level-o/0 – Luis Deras May 09 '16 at 21:13
  • 1
    this has no bearing on xdebug/php.ini settings which could be the cause of the error. It is also possible you application is in a dos loop and continuously looping around a function, no where did OP state they were using laravel and looking at his code sip its likely to be codeigniter – James Kirkby May 16 '16 at 16:08
2

In your case it's definitely the crawler instance is having more Xdebug limit to trace error and debug info.

But, in other cases also errors like on PHP or core files like CodeIgniter libraries will create such a case and if you even increase the x-debug level setting it would not vanish.

So, look into your code carefully :) .

Here was the issue in my case.

I had a service class which is library in CodeIgniter. Having a function inside like this.

 class PaymentService {

    private $CI;

    public function __construct() {

        $this->CI =& get_instance();

   }

  public function process(){
   //lots of Ci referencing here...
   }

My controller as follow:

$this->load->library('PaymentService');
$this->process_(); // see I got this wrong instead  it shoud be like 

Function call on last line was wrong because of the typo, instead it should have been like below:

$this->Payment_service->process(); //the library class name

Then I was keeping getting the exceed error message. But I disabled XDebug but non helped. Any way please check you class name or your code for proper function calling.

A.L
  • 10,259
  • 10
  • 67
  • 98
Develop4Life
  • 7,581
  • 8
  • 58
  • 76
  • Is it an answer or a question? – A.L May 19 '16 at 22:19
  • @daniedad I edited your answer, I think that it's better to write the *solution* in text and not only in comments attached to code. And present form made me think it was a new question and not an answer. Feel free to rollback if you disapprove the changes. – A.L May 20 '16 at 17:13
1

I had a error when i was installing many plugins So the error 100 showed including the location of the last plugin that i installed C:\wamp\www\mysite\wp-content\plugins\"..." so i deleted this plugin folder on the C: drive then everything was back to normal.I think i have to limit the amount of plug-in i install or have activated .good luck i hope it helps

CalvinMD
  • 11
  • 1
1

I had this issue with WordPress on cloud9. It turns out it was the W3 Caching plugin. I disabled the plugin and it worked fine.

sobeit
  • 75
  • 6
1

Another solution if you are running php script in CLI(cmd)

The php.ini file that needs edit is different in this case. In my WAMP installation the php.ini file that is loaded in command line is:

\wamp\bin\php\php5.5.12\php.ini

instead of \wamp\bin\apache\apache2.4.9\bin\php.ini which loads when php is run from browser

Community
  • 1
  • 1
Binod Kalathil
  • 1,939
  • 1
  • 30
  • 43
0

You can also modify the {debug} function in modifier.debug_print_var.php, in order to limit its recursion into objects.

Around line 45, before :

$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
  . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
  . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);

After :

$max_depth = 10;
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
  . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
  . ($depth > $max_depth ? 'Max recursion depth:'.(++$depth) : smarty_modifier_debug_print_var($curr_val, ++$depth, $length));

This way, Xdebug will still behave normally: limit recursion depth in var_dump and so on. As this is a smarty problem, not a Xdebug one!

theredled
  • 998
  • 9
  • 20
-3

I had the same problem and I resolved it like this:

  • Open MySQL my.ini file
  • In [mysqld] section, add the following line: innodb_force_recovery = 1
  • Save the file and try starting MySQL
  • Remove that line which you just added and Save
Kay Angevare
  • 639
  • 6
  • 17