When a user requests a password reset at the login page, with password reset emails enabled, it returns a successful message to the user and emails them a reset token.
If the user requests another reset within that token's window (user.password.reset.ttl), it will still return a successful message to the user but willl fail internally with the message:
DEBUG [o.a.c.u.UserPasswordResetManagerImpl] Failed to reset token and send email. Password reset token is already set for user user@emaildomain.com in domain id: xy with account primary and email user@emaildomain.com
This doesn't appear in the event log of the user either.
versions
4.22.1.0
The steps to reproduce the bug
Have settings enabled for user password reset (user.password.reset.enabled = true) and an email host configured (user.password.reset.smtp.host)
Request a password reset.
Observe the first reset email.
Request another password reset.
What to do about it?
There's a few issues here I think should be addressed:
Consider if password reset attemps should be visible in the user's Event's page. It might create spam in the events list, so might not be a good idea.
Consider either:
Allowing a user to re-request a new password reset token and reset the TTL window using the new token (my desired outcome, and what I'd expect end-users would be familiar with).
If not the above, then wait for the email to be successfully queued/sent and return the success from that. If the email isn't sent due to the token being within the TTL, then return a user-friendly message that they cannot request a new token until a specified datetime.
Allowing a user to re-request a new password reset token and reset the TTL window using the new token (my desired outcome, and what I'd expect end-users would be familiar with).
If not the above, then wait for the email to be successfully queued/sent and return the success from that. If the email isn't sent due to the token being within the TTL, then return a user-friendly message that they cannot request a new token until a specified datetime.
I think a third option could be
if within the ttl window, resend the existing token.
that said handling the silent fail is the major issue.
I had a think about this and I still believe most implementations would issue a new token on each request.
Issuing a new token rotates the token and resets the expiry together. Resending the existing token requires that we either:
Keep the original expiry, which is confusing if the user asks near the end of the window as the link may only work for a few minutes, or
Reset the expiry, which lets a single token live indefinitely, provided the rate limit allows it.
Activity
DaanHoogland commented on Jul 27, 2026
I think a third option could be
that said handling the silent fail is the major issue.
MitchDrage commented on Nov 10, 2026
I had a think about this and I still believe most implementations would issue a new token on each request.
Keep the original expiry, which is confusing if the user asks near the end of the window as the link may only work for a few minutes, or
Reset the expiry, which lets a single token live indefinitely, provided the rate limit allows it.
Raising a PR for option 1.