moeru-ai/airi · error · Error
requestPasswordReset failed
Error message
requestPasswordReset failed
What it means
Wraps authClient.requestPasswordReset({ email, redirectTo }); the literal fires only when better-auth's error carries no message. The endpoint also covers initial credential set (it creates a credential row when none exists), and redirectTo must be the hosted /auth/reset-password page because a file:// URL would break the emailed link.
Source
Thrown at packages/stage-pages/src/pages/settings/account/account-settings-page.vue:319
try {
// NOTICE:
// `redirectTo` MUST live on the API server origin, not on the current
// browser origin. This page is shared with apps/stage-tamagotchi,
// whose Electron renderer loads from `file://` — `window.location.origin`
// would put a `file://` URL into the reset email and break the flow
// for any user who clicks from their inbox. The auth UI is hosted at
// `${SERVER_URL}/auth/reset-password` and reachable from the public
// internet.
// Source: PR #1753 review (chatgpt-codex-connector P1).
//
// The reset-password endpoint also covers the initial-set case — it
// creates a credential row when none exists, see
// node_modules/better-auth/dist/api/routes/password.mjs L152-158.
const redirectTo = new URL('/auth/reset-password', SERVER_URL).toString()
const { error } = await authClient.requestPasswordReset({ email, redirectTo })
if (error)
throw new Error(error.message ?? 'requestPasswordReset failed')
setPasswordSuccess.value = t('settings.pages.account.security.message.setLinkSent', { email })
trackPasswordResetRequested()
}
catch (error) {
setPasswordError.value = errorMessageFrom(error) ?? t('settings.pages.account.security.error.setLinkFailed')
}
finally {
setPasswordLoading.value = false
}
}
// ---- Delete account ----
//
// Two-step flow:
// (1) Click "Delete account" -> open a reka-ui Dialog with a focus-trap and
// overlay so the destructive action is unambiguously modal. Inside the
// dialog the user retypes their email; we only enable the submit button
// when the entered value matches `userEmail` exactly. This is the sameView on GitHub (pinned to 677329427f)
Solutions
- Check the auth server's SMTP/email env configuration — most reset failures are send-side.
- Log error.status/code; 429 means wait before retrying.
- Confirm SERVER_URL is the public auth origin so redirectTo is valid.
- Validate the email format client-side before sending.
Defensive patterns
Strategy: try-catch
Validate before calling
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) {
setPasswordError.value = 'Enter a valid email address'
return
} Try / catch
catch (error) {
if ((error as { status?: number })?.status === 429)
setPasswordError.value = 'Too many requests — try again later'
else
setPasswordError.value = errorMessageFrom(error) ?? t('settings.pages.account.security.error.setLinkFailed')
} Prevention
- Verify SMTP env configuration before enabling the reset flow.
- Rate-limit the request button client-side.
- Keep redirectTo on the hosted auth origin, never a file:// URL.
When it happens
Trigger: Auth server email/SMTP sender misconfigured so the reset mail fails; rate limiting after repeated requests; invalid email format; SERVER_URL wrong so redirectTo is invalid.
Common situations: Dev auth server without SMTP env vars; users requesting multiple resets in a row; running the UI from file:// where the redirect URL cannot work.
Related errors
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/b4d5ffa6ad1739a8.
Report an issue: GitHub.