There is nothing in plain vanilla WordPress that would result in what you described.
It would seem that your problem stems from customizing your process (either by plugin or by your own customization) to populate the user_login with the user's email address to avoid having both a username and email. If it's a custom process that you put in place yourself, then the issue is a result of not thinking through all of the possible issues based on circumventing the core WP process.
When doing something like this, the problem is when the user changes their email address, you also have to account for their username changing. Both email and username must be unique values (display name does not need to be unique). If the user changes their email but the user_login value is their previous email, the validation for unique username will return an error when trying to register the previous email.
It's not a good idea to simply populate the username with the email address. WP intentionally does not have a built in process for changing usernames, and so you have to circumvent that process with a direct db update. Any time you try to do something to "workaround" a core part of WP, you need to ask yourself two questions:
- Is this a good idea?
- Do I really need to do it this way?
If you simply MUST do away with username altogether, a better method is to come up with a way to create a username value from the email address (like extracting the first part) rather than having it be the actual email. BUT... then you still need an additional process during validation to make sure that your autopopulated pseudo username results in a unique value (like if "john" already exists, add "1" to it).
$wpdb->update
is being used instead ofwp_update_user
, a direct database query bypasses all the caching systems, they won't have the chance to flush themselves.