You add fifteen new items to a WordPress navigation menu, hit Save Menu, and reload the page — only ten show up. Or a client fills out a 40-field intake form and half the fields arrive empty on your end. Nothing errors out. No red banner, no log entry that jumps out at you. Data just quietly vanishes past a certain point, and that's usually a PHP setting called max_input_vars doing exactly what it's configured to do.

What you're actually seeing

This one shows up in a few disguises:

  • A WordPress menu (Appearance → Menus) that never keeps more than a fixed number of items, no matter how many times you re-add the missing ones.
  • Advanced Custom Fields repeater or flexible content rows that save fine up to a point, then start dropping the last few rows silently.
  • Gravity Forms, WPForms, or Contact Form 7 forms with 30+ fields where submissions arrive truncated.
  • WooCommerce product pages with a lot of variations where some variations just don't save.
  • Elementor or Divi pages with many widgets where a save "succeeds" but part of the layout reverts.

The common thread: a big form, a lot of individual inputs, and data loss that happens right around the same item count every time.

Why this happens: PHP is counting, not just measuring size

It's tempting to blame this on upload_max_filesize or post_max_size, but those limit the total request size in bytes. This is different. max_input_vars caps the number of individual input variables PHP will accept in a single POST (or GET) request — every checkbox, every hidden field, every array index in a repeater field counts as one.

A WordPress menu with 20 items and a handful of settings per item (label, URL, parent, CSS classes, order) can easily generate 300–500 individual POST fields. ACF repeaters are worse — each row can spawn a dozen or more inputs, so a 40-row repeater might submit 500+ variables on its own. The default PHP value for this directive is 1000, and it doesn't take much to blow past that on a content-heavy site.

When the limit is hit, PHP doesn't throw a fatal error by default. It just stops parsing input variables past the cutoff and silently discards the rest. That's exactly why this is so easy to misdiagnose — there's nothing in error_log unless you've specifically turned on a warning for it.

Confirm it before you touch anything

Don't guess — check the actual value PHP is using for that domain. Create a temporary file (delete it right after):

<?php phpinfo();

Upload it as phpinfo.php in your site's root, load it in a browser, and search the page for max_input_vars. You'll see both the "Local Value" and "Master Value" — if Local shows something like 1000 while your form clearly has more fields than that, you've found your cause. Delete the file as soon as you've checked it; leaving a phpinfo() page public is a small but real information leak.

How to raise it in cPanel

If you're on shared or reseller hosting with cPanel, you almost certainly don't have shell access to edit php.ini directly, and that's fine — there's a UI for it:

  1. Log in to cPanel and open MultiPHP INI Editor under the Software section.
  2. Select your domain from the dropdown.
  3. Switch to Editor Mode (not the basic toggle view) so you can see and edit raw directives.
  4. Find or add the line max_input_vars = 3000 and save.

If you don't see max_input_vars listed at all in Editor Mode, add it manually — the field accepts arbitrary directives, it just won't autocomplete one that isn't already present. Some accounts on older cPanel setups only expose this through a per-domain .user.ini file instead. If MultiPHP INI Editor doesn't stick, create .user.ini in your site's document root with:

max_input_vars = 3000
max_execution_time = 300
max_input_time = 300

.user.ini changes aren't instant — PHP-FPM caches them for up to 5 minutes by default, so give it a few minutes or restart the PHP-FPM service for the account if you have access to do so.

How to raise it on a plain VPS

Without cPanel, you're editing php.ini directly, and the path depends on your PHP handler:

SetupTypical config location
PHP-FPM (Nginx or Apache)/etc/php/8.x/fpm/php.ini or a pool-specific override in /etc/php/8.x/fpm/pool.d/
Apache mod_php/etc/php/8.x/apache2/php.ini
CLI (for wp-cli imports)/etc/php/8.x/cli/php.ini

Edit the relevant file, set max_input_vars = 3000, then restart the matching service:

sudo systemctl restart php8.2-fpm
sudo systemctl restart apache2

If you're running a pool-level override instead of touching the global php.ini, add it inside the pool's .conf file as:

php_admin_value[max_input_vars] = 3000

A php_admin_value line in the FPM pool config can't be overridden by .user.ini or .htaccess at all, which is useful if you manage the box yourself but confusing if you're used to shared hosting where those files just work.

Why not just set it to something huge?

You can, and 3000–5000 covers nearly every real case without any downside worth worrying about — this isn't a memory-hungry setting like memory_limit, it's just a counter. There's no meaningful performance cost to raising it. The only reason not to set it to something absurd like 100000 is that it's usually a sign something else needs fixing — a repeater field with 500 rows on a single page is probably better served by pagination or a custom table than by one enormous form submission anyway.

Prevention: catch it before a client does

  • After any PHP version change in MultiPHP Manager, re-check max_input_vars — some cPanel installs reset per-domain overrides when you switch handlers.
  • If you build sites with ACF repeaters, WooCommerce variations, or long Gravity Forms, set max_input_vars to 3000 as a standard part of your setup checklist rather than waiting for a support ticket.
  • Test with the actual worst-case content count during development — a 5-item test menu will never reveal this bug, but the client's real 30-item menu will.
  • If you migrate a site to SkyServer and it "worked fine on the old host," check whether the old host had a higher default for this directive before assuming the migration broke something.

Frequently Asked Questions

Is max_input_vars the same as post_max_size?

No. post_max_size limits the total size in bytes of a POST request (including file uploads). max_input_vars limits the number of separate input fields, regardless of how small each one is. A form can be well under the size limit and still hit the input-vars limit if it has hundreds of fields.

Why didn't I get an error message?

By default PHP silently truncates input past the limit instead of throwing a fatal error. You can make it visible by checking error_log after enabling display_errors and setting PHP's error reporting to include warnings, but most hosting configs suppress this notice in production, which is exactly why it's easy to miss.

I raised the limit in MultiPHP INI Editor but nothing changed. Why?

Give it five minutes — PHP-FPM caches .user.ini-style overrides and doesn't reread them on every request. If it still hasn't taken effect after that, check whether your theme or plugin sets ini_set() for this directive at runtime (it won't work for max_input_vars specifically, since it can only be set at PHP startup, not via ini_set() mid-request) and confirm you edited the domain that's actually serving the request, not a different account on the same server.

Can I fix this without touching PHP settings at all?

Sometimes. Splitting one giant form into multiple steps, using AJAX to save a repeater incrementally instead of one final submit, or reducing the number of custom fields per row all reduce the input count. For a client site under your control, though, raising the limit is almost always faster and just as safe.

Does this affect GET requests too?

max_input_vars applies to POST, GET, and cookie input arrays combined per request. GET requests rarely hit it because URLs have their own practical length limits long before you'd reach a few thousand parameters, but it's technically the same counter.