Introduction
Must-Use plugins (mu-plugins) in WordPress are automatically activated and cannot be disabled from the admin panel. After migrating a WordPress multisite installation, mu-plugins may stop loading silently - they do not appear in the admin plugins list and their functionality simply disappears. This is particularly problematic because mu-plugins often contain critical site configuration:
# mu-plugins directory exists but plugins not loading
ls -la /var/www/html/wp-content/mu-plugins/
# Files are there, but functionality is missingSymptoms
- Custom functionality from mu-plugins is missing after migration
- mu-plugins directory exists with PHP files but no code executes
- No errors in PHP error log (mu-plugins fail silently)
- Network Admin does not show mu-plugins (they never appear there)
- Other plugins in the regular plugins directory load correctly
Common Causes
- mu-php files placed in subdirectories without a loader file in the root
- File permissions prevent the web server from reading mu-plugin files
- PHP namespace or class conflicts between migrated mu-plugins and existing code
- Migration changed file ownership from the web server user to the migration user
- mu-plugin files have syntax errors that cause silent failure
Step-by-Step Fix
- 1.Verify mu-plugins directory structure. WordPress only loads PHP files directly in the mu-plugins root, not in subdirectories:
- 2.```bash
- 3.ls -la /var/www/html/wp-content/mu-plugins/
- 4.
` - 5.Files must be directly in this directory. If they are in subdirectories, create a loader:
- 6.```php
- 7.// /var/www/html/wp-content/mu-plugins/loader.php
- 8.<?php
- 9.// Load mu-plugins from subdirectories
- 10.foreach (glob(__DIR__ . '/*/mu-plugin.php') as $file) {
- 11.require_once $file;
- 12.}
- 13.
` - 14.Fix file permissions and ownership:
- 15.```bash
- 16.sudo chown -R www-data:www-data /var/www/html/wp-content/mu-plugins/
- 17.sudo find /var/www/html/wp-content/mu-plugins/ -type f -exec chmod 644 {} \;
- 18.sudo find /var/www/html/wp-content/mu-plugins/ -type d -exec chmod 755 {} \;
- 19.
` - 20.Check for PHP syntax errors in each mu-plugin:
- 21.```bash
- 22.for file in /var/www/html/wp-content/mu-plugins/*.php; do
- 23.echo "Checking $file..."
- 24.php -l "$file"
- 25.done
- 26.
` - 27.Add debugging to verify mu-plugins are loading. Create a test file:
- 28.```php
- 29.// /var/www/html/wp-content/mu-plugins/debug-test.php
- 30.<?php
- 31.error_log('mu-plugins/debug-test.php is loading');
- 32.add_action('init', function() {
- 33.error_log('mu-plugin init hook fired');
- 34.});
- 35.
` - 36.Then check the PHP error log:
- 37.```bash
- 38.tail -f /var/log/php8.2-fpm.log | grep "mu-plugin"
- 39.
` - 40.Verify MUPLUGINDIR constant is set correctly in wp-config.php:
- 41.```php
- 42.// Should NOT be defined unless you have a custom mu-plugins location
- 43.// If it is defined, ensure it points to the correct path
- 44.// define('WPMU_PLUGIN_DIR', '/var/www/html/wp-content/mu-plugins');
- 45.// define('WPMU_PLUGIN_URL', 'https://example.com/wp-content/mu-plugins');
- 46.
`
Prevention
- Document all mu-plugins and their purpose in a README within the mu-plugins directory
- Include mu-plugins in your migration checklist and verify loading after each migration
- Add mu-plugin loading verification to your deployment script:
- ```bash
- php -r "require 'wp-load.php'; echo defined('WPMU_PLUGIN_DIR') ? WPMU_PLUGIN_DIR : 'default'; echo PHP_EOL;"
`- Use a loader pattern (loader.php) when organizing mu-plugins in subdirectories
- Keep mu-plugins minimal - they should contain critical site configuration, not feature code
- Test mu-plugins in a staging environment before migration to production
- Monitor PHP error logs for mu-plugin-related warnings after any deployment