I have a custom login page for a blog.

If the user gets the logins incorrect then its re-directing them to wp-login page, but I'd like the error to be echoed out on the custom login page - is that possible?

I have this code, but it doesn't seem to be working:

<?php if ( ! is_user_logged_in() ) { // Display WordPress login form:
 $args = array(
 'label_username' => __( 'Username' ),
 'remember' => true,
 wp_login_form( $args );
<?php } ?>
<div class="wp_login_error">
 <?php if( isset( $_GET['login'] ) && $_GET['login'] == 'failed' ) { ?>
  <p>The password you entered is incorrect, Please try again.</p>
 <?php }
 else if( isset( $_GET['login'] ) && $_GET['login'] == 'empty' ) { ?>
  <p>Please enter both username and password.</p>
 <?php } ?>
</div><!--End WP Login Error-->


1 Answer 1


You may want to checkout wp_signon as that function can provide a WP_Error object with the appropriate error messages on login failure.. the only drawback is that you will have to create your own form or replace the action url on demand.

A somehow basic login function can be implemented like this:

if (!function_exists('custom_login_function')) {
     * Attempts to login a user via POST request.
     * @return boolean
    function custom_login_function()
        if (is_user_logged_in()) {
            throw new \Exception(__('User is already logged in.'), 303);

        $fields = array(
            'nonce'         => 'login_nonce',
            'user_login'    => 'log',
            'user_password' => 'pwd',
            'remember'      => 'remember_me'

        if (!wp_verify_nonce($fields['nonce'], $fields['nonce'])) {
            throw new \Exception(__('Invalid nonce.'), 401);

        $credentials = array();
        array_walk($fields, function(&$field, $key) use ($credentials) {
            if (!empty($_POST[$field])) {
                $credentials[$key] = esc_sql($_POST[$field]);

        $login_status = wp_signon($credentials, is_ssl());

        if (is_wp_error($login_status)) {
            throw new \Exception($login_status->get_error_message(), 401);

        return true;

You can then use it like this:

if (isset($_POST['log'], $_POST['pwd'])) {
    try {

        $redirect = !empty($_POST['redirect_to'] ? $_POST['redirect_to'] : home_url());

    } catch (\Exception $error) {
        $login_error = $error->getMessage(); 

$login_error will then contain the error message thrown by the function or by Wordpress in case the login failed.

Please notice that the function above also checks for a nonce. This is not implemented in the Wordpress login form by default but you can add it to your custom form with a simple function call:

<?php wp_nonce_field('login_nonce', 'login_nonce'); ?>

That will insert a hidden field with the name "login_nonce".

Best regards.

  • To get the nonce from the form i used "if (!wp_verify_nonce($_POST['login_nonce'], $fields['nonce'])) {" instead of "if (!wp_verify_nonce($fields['nonce'], $fields['nonce'])) {". Did I miss something?
    – turboLoop
    Commented Jan 6, 2021 at 21:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.