Hi,
Upfront: I’m not a developer. I ran into this error on my site and worked through the diagnosis with Claude (an AI assistant), which also produced the patch below. I’ve tested it and it resolves the issue on my install, but I can’t vouch for it being the right fix architecturally — please treat the analysis as a lead rather than a conclusion.
Symptom
Every time a logged-out visitor hits /wp-admin/ or /wp-login.php, the site throws a PHP fatal error instead of rendering the intended fake 404:
PHP Fatal error: Uncaught Error: Call to undefined function get_current_screen()
in /wp-includes/admin-bar.php:831
Depending on the server’s display_errors setting, this is either shown publicly (leaking server paths and plugin names) or replaced by the “There has been a critical error on this website” page. Either way the module’s goal — hiding the fact that the site runs WordPress — is defeated, and every bot hit fills up the error log.
This happens in the Custom Login URL module (functions/security/custom-login-url.php), with the redirect option set to “404”.
Analysis
render_404_template() loads the front-end rendering engine from the wp_loaded hook, at a point where WP_ADMIN is already defined (the request entered through wp-admin/admin.php). So is_admin() returns true while the functions in wp-admin/includes/ have not been loaded yet.
Two consequences:
- Any code — core or plugin — that branches on
is_admin()may call an admin function that isn’t available. I hit this first with theacf-openstreetmap-fieldplugin, then with WordPress core itself. is_admin_bar_showing()returnstrueimmediately whenis_admin()is true, without ever reaching theshow_admin_barfilter. The admin bar is therefore built for a logged-out visitor — and it’swp_admin_bar_edit_menu()callingget_current_screen()that triggers the fatal.
One detail that cost several failed attempts: _wp_admin_bar_init() runs on template_redirect, which is fired by template-loader.php. Nulling $wp_admin_bar before the wp() call has no effect — the object is recreated afterwards.
Reproduction
- WordPress 7.1, PHP 8.x
- Classic Monks 2.3.0, Custom Login URL enabled, redirect option set to “404”
- Oxygen Builder as the site builder
- Visit
/wp-admin/in a private window
What worked for me
In render_404_template():
// Load the admin functions missing in this hybrid context
if (!function_exists('get_current_screen')) {
require_once ABSPATH . 'wp-admin/includes/screen.php';
}
// Neutralize the admin bar after the last point where it can be recreated
add_action('template_redirect', static function () {
$GLOBALS['wp_admin_bar'] = null;
}, PHP_INT_MAX);
The require_once clears the fatal and also guards against other plugins making the same assumption. The add_action prevents the admin bar from being rendered to a logged-out visitor — with no CSS (since wp_enqueue_scripts has already fired), it was showing as raw HTML with the WordPress.org links visible.
With both additions, the fake 404 behaves as intended on my site. Obviously this is a local edit that an update will overwrite, hence the report.
Side note
In this same context, Oxygen injects a footer script containing post_id: , — an empty value producing invalid JavaScript. Harmless as far as I can tell, but possibly another symptom of the same underlying issue.
Happy to provide full stack traces or test any fix you’d like to try. Thanks for your work on the plugin.