Password Reset Not Working in Ultimate Member

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)

  1. User opens the Password Reset core page ([ultimatemember_password]).
  2. They submit username or email (_um_password_reset=1).
  3. On template_redirect, UM validates, then (if allowed) queues Password Reset Email (resetpw_email).
  4. User is always redirected to ?updated=checkemail with:

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.

Reset URL shape:

{password-reset-page}?act=reset_password&hash={key}&login={user_login}

  1. UM sets cookie wp-resetpass-{COOKIEHASH} = login:hash.
  2. It redirects to the same page without hash/login in the URL (security: key not left in browser history).
  3. It validates via WordPress check_password_reset_key().
  4. If valid → show set-password form (password-change.php).
  5. 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

RequirementDetail
Core page assignedUltimate Member → Settings → General → Pages → Password Reset
Option keycore_password-reset in um_options
Page contentMust include [ultimatemember_password] (or the Password Reset block)
Reachable by guestsSitewide 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

  1. Confirm Settings → General → Pages → Password Reset points at a real published page.
  2. Edit that page and confirm it contains [ultimatemember_password] only (no conflicting forms).
  3. Open the page logged out. You should see the username/email form.
  4. 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.
  5. 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

SymptomLikely cause
Forgot link 404 / homeCore page deleted or not assigned
Email button goes to homepageEmpty um_get_core_page( 'password-reset' )
Form missing on pageShortcode removed; custom builder block stripped it
Works in one language onlyMultilingual 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

  1. Password Reset Email is disabled
    Settings → Emails → Password Reset Email must be On (resetpw_email_on).
  2. 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.
  3. Wrong / non-existent username or email
    Deliberate anti-enumeration: same checkemail UI, no mail.
  4. 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 for um_dispatch_email.
  5. 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_addr in 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

  1. Temporarily enable a mail logger (e.g. WP Mail Logging) or your SMTP plugin’s log.
  2. Reset with a known approved account and correct email.
  3. Confirm a resetpw_email (subject default: “Reset your password”) was attempted.
  4. If logged as sent but not received → DNS/spam/provider.
  5. 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_attempts user 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)

UM mirrors WordPress:

  1. Link contains hash + login.
  2. First hit sets wp-resetpass-{COOKIEHASH} and strips those query args.
  3. 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.

CauseWhat happens
Browser blocks third-party / all cookiesCookie never stored → invalidkey
ITP / strict privacy / “Prevent cross-site tracking”Same
Opening link in a different browser/app than email client’s in-app browserCookie 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_URICookie set for a path that isn’t used on the follow-up request
Security plugins rewriting cookies / cookie law banners delaying setRace or blocked set
User bookmarks the pre-redirect URL with hash and reuses it laterKey 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 (filter password_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.
  1. Test in a clean private window with cookies allowed.
  2. Click the link once; do not open it twice from the email.
  3. Confirm site URL is consistent (HTTPS, canonical host) in Settings → General and UM pages.
  4. Disable cookie/consent blockers briefly on that domain.
  5. Avoid email “link checkers” / corporate scanners that prefetch the URL (they can consume or confuse the one-time cookie flow).
  6. 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
  • invalidkey appears 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):

  1. The Password Reset core page (and all language variants)
  2. Login / Register / Account core pages (related auth flows)
  3. URLs containing act=reset_password
  4. Query args: updatedhashlogin (or better: bypass cache for the whole page)
  5. Logged-in users (usually already done)
  6. 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

  1. Purge all caches.
  2. Exclude password-reset page permanently.
  3. Request reset → confirm email.
  4. Click link once → you should land on set new password fields (not the username request form).
  5. 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)

PieceLocation / hook
Main logicincludes/core/class-password.php
Shortcode[ultimatemember_password]
Request processum_reset_password_process_hook
Change processum_change_password_process_hook
Send mailUM()->user()->password_reset() → resetpw_email
Kill sendingfilter um_disable_email_notification_sending
Core page URLum_get_core_page( 'password-reset' )
Key APIWP 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

  1. Assign a published Password Reset page with [ultimatemember_password].
  2. Exclude that page (and auth pages) from all full-page caches/CDNs.
  3. Use authenticated SMTP with a From address on your domain.
  4. Keep Password Reset Email enabled; understand checkemail ≠ mail sent.
  5. Know that approved-only and attempt limits silently or loudly block resets.
  6. 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.

Scroll to Top