[note: I solved the problem before asking this question and thought others would find my research/solution helpful, see Can I answer my own question?]
The site in question uses a custom theme and site-specific plugin (that registers custom post types, custom taxonomies, etc), both of which I’ve written.
It turns out that the wp-activate.php
bootstrap results in plugins not being loaded…which came as quite a shock to me (and is not documented anywhere that I can find).
My theme’s header.php
calls one of the methods defined in the site-specific plugin. Since plugins aren’t loaded when wp-activate.php
runs, that method isn’t defined and PHP dies. To make matters worse, the wp-activate.php
bootstrap also disables PHP error messages (even when WP_DEBUG
is set to true), hence, the white screen of death 🙁
Solution
To solve the problem, I hooked into activate_header (the first hook fired after the wp-active.php
bootstrap) and loaded the site-specific plugin myself, as follows:
add_action ('activate_header', 'load_site_specific_plugin') ;
function
load_site_specific_plugin ()
{
if (wp_installing ()) {
require_once (WP_PLUGIN_DIR . 'path to site-specific plugin') ;
}
return ;
}
See the Gory Deatils section below for why I tested wp_installing()
before calling require_once()
.
Alternate Solution
Another solution would be to add a header-wp-activate.php
(that doesn’t rely on any methods defined in the site-specific plugin) to my theme. For my purposes, that didn’t seem to be the right choice, but might be for others.
Gory Details
I have no idea why it was decided that wp-activate.php
should not load plugins. But here’s a description of the relevant parts of the wp-activate.php
bootstrap, and why it results in plugins not being loaded and PHP error messages to not be displayed.
First, wp-activate.php
begins with:
define( 'WP_INSTALLING', true );
Defining WP_INSTALLING
as true has cascading effects throughout the wp-activate.php
bootstrap. Most importantly for the problem I was experiencing, is that wp_get_active_and_valid_plugins() (which is called in wp-settings.php
as part of the bootstrap) contains the following:
if ( empty( $active_plugins ) || wp_installing() )
return array();
Hence, the bootstrap thinks the site doesn’t use any plugins even tho get_option('active_plugins')
returns a non-empty array.
To understand why no PHP errors were output when WP died while trying to load my theme’s header.php
(again, even tho I have define ('WP_DEBUG', true) ;
), we have to look at the way wp_debug_mode() is written. wp_debug_mode()
is called before the call to wp_get_active_and_valid_plugins()
during the wp-activate.php
bootstrap and contains the following:
if ( defined( 'XMLRPC_REQUEST' ) || defined( 'REST_REQUEST' ) || ( defined( 'WP_INSTALLING' ) && WP_INSTALLING ) || wp_doing_ajax() ) {
@ini_set( 'display_errors', 0 );
}
So, not only does the wp-activate.php
bootstrap not load any plugins, it also causes PHP errors that result from that fact to not be displayed; hence, the white screen of death! Argh!!!
Can anyone explain to my why it was decided that the wp-activate.php
bootstrap should act this way?
TL;DR: see the comment I left on a thread about the Nextgen Bootstrap/Load Feature Project on Make WordPress Core.