I debugged a strange WordPress issue for a client today, one I hadn’t seen or heard of before, so I thought I’d document it.
- IE7 would try to download the wp-login.php page instead of loading it.
- Mobile devices (using my mobile plugin would complain that they could not view the site due to the wrong content type (perhaps showing a 406 error).
- The feeds were not validating.
And other problems that had already been fixed:
- All plugins were deactivated.
- The theme had reverted to the WordPress default theme.
All of these symptoms ended up being caused by a single problem (technically, multiple instances of the same problem). The WordPress options table (normally named wp_options) had recently had problems, and a variety of settings had been flagged in a ‘notoptions’ cache.
I hadn’t seen the ‘notoptions’ cache before, but it appears to be a list of options that were requested, but that did not exist in the options table (or were not returned as expected by a query). When the options table was having problems, this ‘notoptions’ list grew to include things it shouldn’t have. Specifically, it was including:
- html_type – which tells the browser to serve the pages (in most cases) as text/html.
- blog_charset – which tells the browser what character set the pages are in.
- plugins – which plugins are active.
- template/stylesheet – which theme to show.
With these things in the ‘notoptions’ list all sorts of stuff broke. WordPress wasn’t getting the information for these options, and it was information is needed to work properly. While I was tracing code to find out what was going on, I discovered the ‘notoptions’ references in the
get_option() function (line 206 wp-includes/functions.php). Commenting out the code that returned if the requested option was in the ‘notoptions’ list seems to allow the rest of the code to flow properly and also reset the ‘notoptions’ list to exclude the settings that actually do exist.
The lines I commented out were 215-217:
$notoptions = wp_cache_get('notoptions', 'options');
if ( isset($notoptions[$setting]) )
After that ran once, everything worked properly again.
Hopefully this will be helpful to others that find themselves in similar situations.
(Posted with client permission)