To mitigate denial of service attacks, PHP 5.3.9 introduced a max-input-vars configuration that defaults to 1000. This has also been backported to some 5.2.x security builds bundled with Ubuntu and other major Linux distributions.
Each menu item on the admin/structure/menu/manage/MENU_NAME form adds several POST variables of the form mlid:$i[...]. The max-input-vars value applies to each level in a multidimensional array, not to the total number of variables, so even though several subvariables within the square brackets are posted, each menu item counts as just one variable against the 1000 limit. Still, for sites with >1000 items in a menu, this results in a broken administration page.
A possible fix is to group the submitted data into partitioned subarrays, so that no single array exceeds 1000.
Comments
Comment #1
jurgenhaasWe just ran into this very same problem and had some internal discussions on how to approach it. Here are some thoughts:
First of all, while Drupal is generating a form, it knows the limit from max_input_vars and it knows the number of fields in the form (including the hidden ones). So we do know for sure if we deliver a form to the browser that will certainly unsubmittable (if that's a word that exists). In this case, a drupal_set_message would be extremely helpful to prevent people from pulling their hair out as they won't knwo why they get no effect when hitting that submit button.
But of course, that's no solution to the problem itself.
For us the first question was, if this is a problem purely related to admin/structure/menu/manage/MENU_NAME or if we have other areas of potential similar problems. Regarding core we can certainly think of admin/people/permissions (although a nice solution already exists: the module filter_perms) and also admin/structure/taxonomy/TAXONOMY_NAME. Everything else is usually paged and therefore prevents that huge number of form elements.
Things like "Manage Menu" and "Manage Taxonomy Terms" can not be paged as long as we want to allow that Drag&Drop functionality, which I guess is essential.
However, those pages are not really usable as they are today and maybe that's the route to take to go after both issues at the same time: usability and huge number of form elements.
Either there is a way to trim down those forms by always only displaying a subset of the whole thing and then provide clever javascript and ajax driven interactivity to change the scope dynamically or, and that's maybe the better approach, we still deliver the whole form and instead of submitting everything through the submit button, we could submit individual changes via ajax as they get changed and the server stores those changes in the cache which will then be executed when the final submit action is taken. Having said that, this second approach does not address the usability issue though.
Any thoughts on this from others?
Comment #2
tangent commentedPart of the reason that the current menu admin page is a single massive form is doubtless that reliance on AJAX, or even Javascript, would be an issue for some.
I also have this issue on the website that I manage. It is currently impossible to use the menu admin page.
The way forward may involve adding a filtering form at the top, perhaps something like the node filter form. There are a variety of filtering solutions scattered across many contrib modules to draw inspiration from though. Perhaps the filtering would only be visible above a certain number of menu items.
Comment #3
j0rd commentedFor me, I ran into this problem because of suhosin settings, which is also set to 1000. This patch as mentioned is available in versions previous to 5.3.9, for instance debian lenny.
Here's my post about this issue in Display Suite's issue queue, I explain the problem and what's it's causing Drupal to do.
#1870014: Admin Interface Fail: PHP max_input_vars & suhosin post variable limit with a node with lots of fields (50+).
Changing the component to ajax, as this is an ajax issue, and menu is a casualty of it, as is display suite.
Here are some other related core issues regarding this:
#329056: Unable to save changes to menu
#1565704: Core Web UI interfaces can go over php's max_input_vars
Comment #4
j0rd commentedtagging.
Comment #5
j0rd commentedtagging
Comment #6
ayalon commentedI searched this for hours:
If you have a menu with 250 entries, any changes to menu items will not be savedwith php 5.3.9. Every menu item has 4 post variables = 4 * 250 = 1000 variables
Change the php.ini file
max_input_vars=50000
or someting like that and restart your server daemon.
Comment #7
j0rd commented@ayalon. You seem to be correct. Each menu item has:So as you mentioned, I assume this will fail after 250 items with max_input_vars at 1000. Going to update the title & description to reflect this and hopefully we'll get more eyes on it.UPDATE: I was in-correct after looking into this further. As mentioned in the OP, the limit applies to only each level of the _POST array.
So you can have 1000 first level items, and for each of those, you can also have another 1000 keys for a total of 1,000,000 and this will work just fine and not cause problems with max_input_vars (post_max_size is another story). This limit was put in place to avoid hash collisions. Since the form also posts form_build_id, form_token, form_id & op you're left with 996 menu items most likely.
Comment #8
j0rd commentedChanging title back. Sorry.
Comment #9
dman commentedJust to say this is still outstanding, and wasn't something I could find in searching on d.o (or anywhere) until *after* I'd fully identified the problem and knew the keywords.And came here..
It presented to me as
* Editing a large menu (close to 600 rows) with the menu UI
* submitting the form did not save, and actually complained 'The form has become outdated'
This was a 'live' server case only - as local dev did not have suhosin configs like that. At least my inability to replicate locally pointed me at the OS/settings as a culprit.
'The form has become outdated' was a real red herring of a message, but investigation led me to conclude that the POST data was getting truncated, as the token at the end of the form seemed to be getting lost.
I tried shifting the 'submit' button and hidden form values to the top of the form (abusing the theme_menu_overview_form() function) and got ... different results. This made me feel I was on the right track re truncation.
With Apache/PHP logging turned up to verbose, I found
Although I knew there was such a thing as max_post size, and soon found 'max_input_vars' - those did not fix the issue.
Only after adding
into php.ini and a HARD Apache restart did my menu start working again.
This was hard to trace!
Phew.
If your menu is too big to manage, you can try Big Menu
- which rewrites the menu admin UI to use AJAX loads (as suggested above). And therefore sidesteps this issue.
However, I'd written it to avoid UI overload, not server limitations, so didn't go straight to it in this case. We can deal with 'several hundred' items in the main architecture - I'd switch to bigmenu about the 800 mark. Or - maybe today.
Comment #10
datvance commentedJust to update in case someone like me finds this later and is confused, the limit applies to all levels combined...
https://bugs.php.net/bug.php?id=62921
Comment #11
dmegatool commentedAs suggested by @dman in post #9, Big Menu is a solution. People working with the site actually prefer it as it's less scrolling. It fixed the problem for me. Maybe if I wasn't on a shared hosting I would have looked futher but for now, it's doing the job. Thanks man !
Comment #12
retiredpro commentedThank you, @ayalon. Your solution in #6 worked for me.
Comment #17
catchMarking this as duplicate of #2742371: Drag and drop interfaces can break either browsers or exceed PHP server limits for forms which is critical.