Password reset is one of the most common real-world Ultimate Member breakages. Official docs barely cover it because the failure is rarely “UM is broken”—it’s usually page misconfiguration, email delivery, cookies, or full-page caching colliding with how WordPress reset keys work.
This guide walks the real flow in UM, then the four failure domains that cause most tickets: reset page, SMTP/email, cookies, and cache.
How Ultimate Member password reset actually works
UM does not invent its own reset system. It wraps WordPress core keys and a cookie handoff, on a dedicated core page.
Request flow (forgot password)
- User opens the Password Reset core page (
[ultimatemember_password]). - They submit username or email (
_um_password_reset=1). - On
template_redirect, UM validates, then (if allowed) queues Password Reset Email (resetpw_email). - User is always redirected to
?updated=checkemailwith:
If an account matching the provided details exists, we will send a password reset link…
That message is not proof an email was sent. Unknown users and (by default) non-approved users get the same screen. No email goes out in those cases.
Email link flow (set new password)
Reset URL shape:
{password-reset-page}?act=reset_password&hash={key}&login={user_login}
- UM sets cookie
wp-resetpass-{COOKIEHASH}=login:hash. - It redirects to the same page without
hash/loginin the URL (security: key not left in browser history). - It validates via WordPress
check_password_reset_key(). - If valid → show set-password form (
password-change.php). - On success → WordPress
reset_password(), clear cookie, redirect to login with?updated=password_changed.
Users are not auto-logged in after a forgot-password reset. They must sign in with the new password.
1. Reset page problems (most common structural failure)
What must be true
| Requirement | Detail |
|---|---|
| Core page assigned | Ultimate Member → Settings → General → Pages → Password Reset |
| Option key | core_password-reset in um_options |
| Page content | Must include [ultimatemember_password] (or the Password Reset block) |
| Reachable by guests | Sitewide restriction skips this page by design |
If the page is missing, unpublished, wrong, or empty of the shortcode:
- “Forgot your password?” links go nowhere / wrong URL
{password_reset_link}in email can be empty or point at the wrong place- After clicking the email, validation redirects fail (
invalidkey/ blank page)
Checklist
- Confirm Settings → General → Pages → Password Reset points at a real published page.
- Edit that page and confirm it contains
[ultimatemember_password]only (no conflicting forms). - Open the page logged out. You should see the username/email form.
- On multilingual sites (WPML/Polylang), confirm each language has a mapped password-reset page. A link generated in EN that lands on a DE page without the cookie/path match often shows invalid key.
- Do not put the shortcode on a random “Contact” page and expect core redirects to find it—UM uses the assigned core page URL for emails and redirects.
Symptom → cause
| Symptom | Likely cause |
|---|---|
| Forgot link 404 / home | Core page deleted or not assigned |
| Email button goes to homepage | Empty um_get_core_page( 'password-reset' ) |
| Form missing on page | Shortcode removed; custom builder block stripped it |
| Works in one language only | Multilingual page mapping incomplete |
Fix: Reassign or recreate the core page (UM’s “Install Core Pages” notice if offered), put the shortcode back, retest logged out.
2. SMTP / email (the “I got checkemail but nothing arrived” case)
UM does not ship SMTP. Path is:
password_reset() → um_dispatch_email → UM()->mail()->send() → wp_mail()
If wp_mail() fails (or never runs), users still see the success-style checkemail screen.
Silent “no email” causes inside UM
- Password Reset Email is disabled
Settings → Emails → Password Reset Email must be On (resetpw_email_on). - User is not Approved (default)
Setting Only allow approved users to reset password (only_approved_user_reset_password, default on) means awaiting email / pending / inactive users get checkemail but no mail. - Wrong / non-existent username or email
Deliberate anti-enumeration: same checkemail UI, no mail. - Action Scheduler delay/failure
If Enable Action Scheduler for email sending is on, mail is queued. Stuck/failed jobs = delayed or never-sent mail. Check pending/failed AS actions forum_dispatch_email. - Broken
{password_reset_link}
Link is built when the email is queued, using the core password-reset page. If that page URL is empty, the button is useless even if the email arrives.
SMTP / deliverability (outside UM)
Typical stack failures:
- No SMTP plugin; host blocks
phpmailer/ port 25 - From address not aligned with authenticated SMTP domain (
mail_from/mail_from_addrin UM Emails settings) - SPF/DKIM/DMARC fail → spam folder or soft bounce
- Security plugins blocking outbound mail
- Shared hosting rate limits
How to verify email actually fires
- Temporarily enable a mail logger (e.g. WP Mail Logging) or your SMTP plugin’s log.
- Reset with a known approved account and correct email.
- Confirm a
resetpw_email(subject default: “Reset your password”) was attempted. - If logged as sent but not received → DNS/spam/provider.
- If never logged → UM setting, approval status, AS queue, or code killing send via
um_disable_email_notification_sending.
Rate limit that looks like “email broken”
Settings → Access → Other → Reset Password:
- Limit enabled by default
- Default max attempts: 3 (
password_rst_attemptsuser meta)
After the limit:
You have reached the limit for requesting password change…
Clear by successful reset, successful login (wp_login clears attempts), or manually clearing that user meta. Admins can be excluded via the admin limit-disable option when present.
3. Cookies (invalid key right after opening a “good” email)
This is the most confusing UX: email looks correct, user clicks once, and UM says:
- Your password reset link appears to be invalid… (
updated=invalidkey) - or …has expired… (
updated=expiredkey)
Cookie handoff (by design)
UM mirrors WordPress:
- Link contains
hash+login. - First hit sets
wp-resetpass-{COOKIEHASH}and strips those query args. - Second request must send that cookie back; otherwise key check fails →
invalidkey.
So anything that blocks or mismatches cookies breaks reset even when the key in the email is valid.
Common cookie breakers
| Cause | What happens |
|---|---|
| Browser blocks third-party / all cookies | Cookie never stored → invalidkey |
| ITP / strict privacy / “Prevent cross-site tracking” | Same |
| Opening link in a different browser/app than email client’s in-app browser | Cookie set in WebView A, form opens in Browser B |
HTTP vs HTTPS mismatch / wrong domain (www vs bare) | Cookie path/domain doesn’t match next request |
Cookie path from odd REQUEST_URI | Cookie set for a path that isn’t used on the follow-up request |
| Security plugins rewriting cookies / cookie law banners delaying set | Race or blocked set |
| User bookmarks the pre-redirect URL with hash and reuses it later | Key already consumed or cookie flow skipped incorrectly |
UM calls nocache_headers() when setting the cookie, but that only helps the cookie-set response—not a cached HTML page in front of it (see cache section).
Expired vs invalid
expiredkey: WordPress reset key lifetime exceeded (filterpassword_reset_expiration, typically ~1 day). Or user requested a new reset (new key invalidates the old one).invalidkey: Cookie missing/mismatched, key wrong, already used, or page/cookie path broken.
Cookie troubleshooting steps
- Test in a clean private window with cookies allowed.
- Click the link once; do not open it twice from the email.
- Confirm site URL is consistent (HTTPS, canonical host) in Settings → General and UM pages.
- Disable cookie/consent blockers briefly on that domain.
- Avoid email “link checkers” / corporate scanners that prefetch the URL (they can consume or confuse the one-time cookie flow).
- After one failed click, request a fresh email—don’t keep retrying the same link.
4. Cache (the silent killer of password reset)
Full-page cache is the #1 infrastructure reason reset “randomly” fails on otherwise healthy sites.
Why cache breaks this flow
Password reset needs:
- Fresh POST handling for the request form
- A Set-Cookie + redirect on
?act=reset_password&hash=…&login=… - A follow-up request that sees the cookie and renders the change form
- Dynamic
?updated=messages
If a CDN/plugin serves cached HTML for the password-reset page:
- POST may never hit PHP
- Cookie may never be set
- User may see a stale “request form” instead of the change-password form
invalidkeyappears even with a valid email link- checkemail / error banners don’t update
UM only sends nocache_headers() when setting the reset cookie—not on every view of the page. You must exclude the page at the cache layer.
What to exclude from cache
Always exclude (by URL and/or cookie):
- The Password Reset core page (and all language variants)
- Login / Register / Account core pages (related auth flows)
- URLs containing
act=reset_password - Query args:
updated,hash,login(or better: bypass cache for the whole page) - Logged-in users (usually already done)
- Cookie
wp-resetpass-*if your cache supports cookie-based bypass
Applies to: WP Rocket, LiteSpeed, Cloudflare, NitroPack, SG Optimizer, Host cache, etc.
Object / user cache notes
UM deletes um_cache_userdata_{user_id} when generating a reset URL. That is not a substitute for excluding the page from full-page cache. Don’t rely on object-cache plugins to “fix” password reset.
Cache verification
- Purge all caches.
- Exclude password-reset page permanently.
- Request reset → confirm email.
- Click link once → you should land on set new password fields (not the username request form).
- If you still see the request form with
invalidkey, cache or cookies are still interfering.
Symptom decision tree
User submits reset form
│
├─ Error: empty username/email → fill the field
├─ Error: request limit → clear attempts / wait / login once
└─ Sees checkemail
│
├─ No email in logger → email Off / not approved / wrong user / AS / wp_mail
├─ Email in logger, not in inbox → SMTP/DNS/spam
└─ Email received
│
├─ Link host wrong / 404 → fix core Password Reset page
├─ invalidkey immediately → cookies / cache / path / prefetch
├─ expiredkey → new request; don’t reuse old link
└─ Change form shows
│
├─ Strong password / mismatch errors → fix password rules
└─ Success → login with new password (no auto-login)
Settings map (where to look in admin)
Pages
- Ultimate Member → Settings → General → Pages → Password Reset
Access / limits
- Settings → Access → Other → Reset Password
- Enable limit / max attempts
- Only approved users can reset (default on)
Emails
- Settings → Emails → Password Reset Email (and From name/address)
- Optional: Action Scheduler email sending
- Also: Password Changed Email after success
Appearance / security
- Strong password requirements affect the change form
- Login form “Forgot password?” link must point at the core page
Developer notes (when you need to debug code)
| Piece | Location / hook |
|---|---|
| Main logic | includes/core/class-password.php |
| Shortcode | [ultimatemember_password] |
| Request process | um_reset_password_process_hook |
| Change process | um_change_password_process_hook |
| Send mail | UM()->user()->password_reset() → resetpw_email |
| Kill sending | filter um_disable_email_notification_sending |
| Core page URL | um_get_core_page( 'password-reset' ) |
| Key API | WP get_password_reset_key / check_password_reset_key / reset_password |
Custom code that calls UM()->password()->reset_url() multiple times in one request is safe (static key cache). Regenerating keys elsewhere between “email built” and “user clicks” will invalidate the emailed link.
Minimum production harden list
- Assign a published Password Reset page with
[ultimatemember_password]. - Exclude that page (and auth pages) from all full-page caches/CDNs.
- Use authenticated SMTP with a From address on your domain.
- Keep Password Reset Email enabled; understand checkemail ≠ mail sent.
- Know that approved-only and attempt limits silently or loudly block resets.
- Tell users: one click, same browser, cookies allowed, request a new link after any error.
Most “UM password reset is broken” tickets resolve to: wrong/missing reset page, mail never left the server, cookie blocked or path-mismatched, or cached HTML short-circuiting the cookie redirect. Fix those four before assuming a plugin bug.


