Fixing the Elementor 4.1.3 Front-End Fatal: Call to undefined function is_plugin_active()
Elementor 4.1.3 can take down a site with a fatal error - Call to undefined function is_plugin_active(). The public pages go down, and so does the login screen, while the wp-admin dashboard - if you already have a session open - keeps insisting everything is fine and fully up to date. This is a bug in Elementor itself, not a plugin conflict, and counter-intuitively it tends to hit the leanest installs hardest. The fix is a two-line mu-plugin. Here is that first, then why it happens.
Seen on Elementor 4.1.3, on the WordPress front-end. It is not PHP-version specific, and there is no Elementor Pro dependency.
Read the error
Here is the fatal as it lands in the PHP error log on a plain page request:
[11-Jun-2026 10:40:53 UTC] PHP Fatal error: Uncaught Error: Call to undefined function Elementor\Core\Utils\is_plugin_active() in /path/to/wordpress/wp-content/plugins/elementor/core/utils/hints.php:366
Stack trace:
#0 /path/to/wordpress/wp-content/plugins/elementor/modules/widget-creation/angie-promotion.php(32): Elementor\Core\Utils\Hints::is_plugin_active()
#1 /path/to/wordpress/wp-content/plugins/elementor/modules/widget-creation/angie-promotion.php(19): Elementor\Modules\WidgetCreation\AngiePromotion::should_display_promotion()
#2 /path/to/wordpress/wp-content/plugins/elementor/modules/widget-creation/module.php(42): Elementor\Modules\WidgetCreation\AngiePromotion::init()
#3 /path/to/wordpress/wp-content/plugins/elementor/core/base/module.php(86): Elementor\Modules\WidgetCreation\Module->__construct()
#4 /path/to/wordpress/wp-content/plugins/elementor/core/modules-manager.php(64): Elementor\Core\Base\Module::instance()
#5 /path/to/wordpress/wp-content/plugins/elementor/includes/plugin.php(712): Elementor\Core\Modules_Manager->__construct()
#6 /path/to/wordpress/wp-content/plugins/elementor/includes/plugin.php(630): Elementor\Plugin->init_components()
#7 /path/to/wordpress/wp-includes/class-wp-hook.php(324): Elementor\Plugin->init()
#8 /path/to/wordpress/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters()
#9 /path/to/wordpress/wp-includes/plugin.php(517): WP_Hook->do_action()
#10 /path/to/wordpress/wp-settings.php(704): do_action()
#11 /path/to/wordpress/wp-config.php(112): require_once('/path/to/wordp...')
#12 /path/to/wordpress/wp-load.php(50): require_once('/path/to/wordp...')
#13 /path/to/wordpress/wp-blog-header.php(13): require_once('/path/to/wordp...')
#14 /path/to/wordpress/index.php(17): require('/path/to/wordp...')
#15 {main}
thrown in /path/to/wordpress/wp-content/plugins/elementor/core/utils/hints.php on line 366
Note where it fires: a plain front-end request (index.php to wp-blog-header.php), nowhere near wp-admin. That detail is the whole story. The same is true of wp-login.php, which is why you can find yourself locked out of the login screen while a dashboard you already had open keeps reporting that all is well.
Add the mu-plugin
If you are mid-outage, this is the part to act on first. Create the file wp-content/mu-plugins/000-is-plugin-active-shim.php - the mu-plugins folder may not exist yet, so add it, and mind the hyphen. Drop in the following:
<?php
/**
* MU-plugin: make is_plugin_active() available on the front-end.
*
* Works around an Elementor Angie-promotion fatal where Hints::is_plugin_active()
* calls the wp-admin-only is_plugin_active() during 'init' on front-end requests,
* where wp-admin/includes/plugin.php is never loaded.
*/
if ( ! function_exists( 'is_plugin_active' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
The full file is also on GitHub. Must-use plugins are the right tool here because they load during wp-settings.php, before regular plugins and well before init, so the function exists by the time Elementor reaches for it. Re-enable everything, reload the front-end, and the fatal is gone.
Why it happens
is_plugin_active() lives in wp-admin/includes/plugin.php, a file WordPress only loads for genuine wp-admin requests - never on the front-end, and never on wp-login.php. Elementor’s own Hints class knows this - look at is_plugin_installed(), which guards the include before using a sibling function. Its neighbour is_plugin_active() on line 366 does not:
// Guards correctly:
public static function is_plugin_installed( $plugin ): bool {
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
// ...
}
// Doesn't - line 366 is the fatal:
public static function is_plugin_active( $plugin ): bool {
$plugin = self::ensure_plugin_folder( $plugin );
return is_plugin_active( $plugin );
}
They clearly knew the file needs loading - they do it fifteen lines up - and simply missed the same guard here. The trigger is AngiePromotion::init(), which runs on the init hook and calls should_display_promotion() to Hints::is_plugin_active('angie') as its very first statement, with nothing gating it. So it fires on essentially every front-end request.
Why it only takes down some sites
It comes down to load order. The fatal only surfaces when nothing else has already loaded wp-admin/includes/plugin.php earlier in the request. Plenty of plugins - WooCommerce among them - pull that file in themselves for their own reasons, which silently masks the bug. A busy 40-plugin site sails on while a lean install dies on the same Elementor version.
This also flips the usual debugging instinct on its head. Stripping back to Elementor-only does not cause the fatal; it removes the thing that was accidentally hiding it. That is why “disable everything except Elementor” makes the problem worse, not better, and why a fresh plugin re-upload and a round of cache clears do nothing - the code is broken and being faithfully reproduced, not corrupted or stale.
It also explains a moment that looks like a contradiction. Re-enable Elementor from the Plugins screen and the toggle works, the dashboard stays up, yet the front-end goes down the instant the plugin is active again. The admin is simply the one place is_plugin_active() is always defined - so it is the worst possible vantage point for judging whether the site is actually up. Test from the front-end or a logged-out window, not from inside wp-admin.
The proper fix
Upstream, the fix is simply to mirror the guard that already exists fifteen lines up:
public static function is_plugin_active( $plugin ): bool {
if ( ! function_exists( 'is_plugin_active' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugin = self::ensure_plugin_folder( $plugin );
return is_plugin_active( $plugin );
}
I have reported it to Elementor as issue #36184. In the meantime the shim is safe to leave in permanently - it no-ops on admin requests, where the function is already defined, and it will keep doing nothing once Elementor adds the guard.
And that’s it. The shim holds, the site is back, and you can carry on updating Elementor without the bug returning.