Fix Wordpress "Fatal error: Allowed memory size" messages

You may (or may not) have noticed this site was down for the past few days, displaying a blank page no matter what URL was entered. After recalling that I had turned off PHP error onscreen outputting, I was presented with this lovely message:

Fatal error: Allowed memory size of 33554432 bytes exhausted
(tried to allocate XX bytes) in /some/file on line XX

This is a general PHP error, but the exact amount (33554432 bytes) occurs very frequently on Wordpress sites. Here’s what’s happening, and how to fix it.

Every installation of PHP has an ini value called memory_limit, which hardcaps how much memory PHP may use on any given request. There are other ini settings that dictate the memory usage for specific actions, like post_max_size, but this one is universally applied; you can’t load anymore than what this value dictates.

I do a lot of stuff with files in PHP, so I blow this value out from it’s default of 128 MB up to 2 GB. I set this globally in my php.ini file like so:

memory_limit = 2G

I could also set this value from inside an .htaccess file:

php_value memory_limit 2G

Since this value was set before the site even loads, imagine my surprise when PHP is telling me that the limit is now 33554432 bytes, or 32 MB. The limit was changed by a define in Wordpress called WP_MEMORY_LIMIT. Here’s where things go awry. Wordpress tries to check the existing memory_limit before applying it’s own terms, however the value must be set in terms of MB. Look back at my example settings; the PHP memory shorthand allows me to set in gigabytes using a “G”. But Wordpress does a straight integer comparison to figure out if the existing setting is more/less than 32 MB. Here’s the offending code, a portion of an if statement on line 42 in wp-includes/default-constants.php

( (int) @ini_get('memory_limit') < abs(intval(WP_MEMORY_LIMIT)) ) )

What you end with in that sample is essentially if (2 < 32), which resolves true and thus Wordpress applies it’s own default limits.

You have three options to rectify the situation: two easy fixes, plus one badass “server-baller” fix. First the easy ones. As Wordpress outlines in the article on increasing memory, simply define WP_MEMORY_LIMIT in wp-config.php using MB syntax. If I wanted to set it to 2 GB, it would look like this:

define('WP_MEMORY_LIMIT', '2048M');

Your value will be honored as long as it is an integer value greater than 32, but could break if Wordpress changes it’s memory size comparison calculation.

Alternatively, I could change my the memory_limit setting directly in php.ini or .htaccess to use MB syntax:

[php.ini]
memory_limit = 2048M

[.htaccess]
php_value memory_limit 2048M

Realistically I would probably edit php.ini. Well, that is, I would, if I didn’t know about the badass server-baller third option, which overrides php.ini AND prevents Wordpress (or any other site for that matter) from making any changes to the value.

Look back at my .htaccess setting, and notice that I set the value using the command php_value. PHP has a similar command called php_<span class='red'>admin</span>_value, which you can use for setting all the same stuff as php_value.

The difference: php_admin_value can only be set within Apache configurations, i.e. it cannot be used inside of .htaccess files. Furthermore, any value set using php_admin_value cannot be overridden by any later calls to php_value or ini_set. You can override php.ini defaults, and lock that value in for the remainder of the request.

So back to our Wordpress example, I opened the VirtualHost for frankkoehl.com and entered this line:

php_admin_value memory_limit 2G

Now the site will always allow a memory limit of 2 GB, no matter what. Wordpress can try and set whatever value it likes, it will never be recognized.

Note that this function requires that you have access to Apache configurations, at least the ones running your site. Most shared hosting packages won’t offer this level of access.

It’s worth mentioning that Wordpress sets a default value of 32 MB, lower than PHP’s own default of 128 MB. I disagree that such a low limit is necessary, but they are trying to be good stewards to servers everywhere, so I can see where they’re coming from.

I still have no idea why this memory issue popped up in the first place, but it gave me an excuse to share a cool configuration option that has saved me from having to scour code on several bloated, crappy sites to find obscure ini settings. I have a recent real-world example you can read about on Stack Overflow.