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:

bash
# mu-plugins directory exists but plugins not loading
ls -la /var/www/html/wp-content/mu-plugins/
# Files are there, but functionality is missing

Symptoms

  • 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. 1.Verify mu-plugins directory structure. WordPress only loads PHP files directly in the mu-plugins root, not in subdirectories:
  2. 2.```bash
  3. 3.ls -la /var/www/html/wp-content/mu-plugins/
  4. 4.`
  5. 5.Files must be directly in this directory. If they are in subdirectories, create a loader:
  6. 6.```php
  7. 7.// /var/www/html/wp-content/mu-plugins/loader.php
  8. 8.<?php
  9. 9.// Load mu-plugins from subdirectories
  10. 10.foreach (glob(__DIR__ . '/*/mu-plugin.php') as $file) {
  11. 11.require_once $file;
  12. 12.}
  13. 13.`
  14. 14.Fix file permissions and ownership:
  15. 15.```bash
  16. 16.sudo chown -R www-data:www-data /var/www/html/wp-content/mu-plugins/
  17. 17.sudo find /var/www/html/wp-content/mu-plugins/ -type f -exec chmod 644 {} \;
  18. 18.sudo find /var/www/html/wp-content/mu-plugins/ -type d -exec chmod 755 {} \;
  19. 19.`
  20. 20.Check for PHP syntax errors in each mu-plugin:
  21. 21.```bash
  22. 22.for file in /var/www/html/wp-content/mu-plugins/*.php; do
  23. 23.echo "Checking $file..."
  24. 24.php -l "$file"
  25. 25.done
  26. 26.`
  27. 27.Add debugging to verify mu-plugins are loading. Create a test file:
  28. 28.```php
  29. 29.// /var/www/html/wp-content/mu-plugins/debug-test.php
  30. 30.<?php
  31. 31.error_log('mu-plugins/debug-test.php is loading');
  32. 32.add_action('init', function() {
  33. 33.error_log('mu-plugin init hook fired');
  34. 34.});
  35. 35.`
  36. 36.Then check the PHP error log:
  37. 37.```bash
  38. 38.tail -f /var/log/php8.2-fpm.log | grep "mu-plugin"
  39. 39.`
  40. 40.Verify MUPLUGINDIR constant is set correctly in wp-config.php:
  41. 41.```php
  42. 42.// Should NOT be defined unless you have a custom mu-plugins location
  43. 43.// If it is defined, ensure it points to the correct path
  44. 44.// define('WPMU_PLUGIN_DIR', '/var/www/html/wp-content/mu-plugins');
  45. 45.// define('WPMU_PLUGIN_URL', 'https://example.com/wp-content/mu-plugins');
  46. 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