© 2026 Hedgehog Software, LLC

TwitterGitHubDiscord
More
CommunitiesDocsAboutTermsPrivacy
Search
Star
Setup for Free
SupabaseS
Supabase•2mo ago•
1 reply
Despair

Question about handling OTP recovery errors (Supabase / auth flow)

self-hostedauth
I’m implementing a password recovery flow using
verifyOtp
verifyOtp
+
updateUser
updateUser
, and I’m unsure how to properly handle a specific edge case.

Current flow (simplified):

// Verify recovery token
const { error: recoveryError } = await client.auth.verifyOtp({
  email: bodyPayload.email,
  token: bodyPayload.code,
  type: "recovery",
});
if (recoveryError) {
  return NextResponse.json(
    { message: `Failed to verify recovery token: ${recoveryError.message}` },
    { status: 500 },
  );
}

// Change password
const { error: updateError } = await client.auth.updateUser({
  password: bodyPayload.password,
});
if (updateError) {
  return NextResponse.json(
    { message: `Failed to change password: ${updateError.message}` },
    { status: 500 },
  );
}
// Verify recovery token
const { error: recoveryError } = await client.auth.verifyOtp({
  email: bodyPayload.email,
  token: bodyPayload.code,
  type: "recovery",
});
if (recoveryError) {
  return NextResponse.json(
    { message: `Failed to verify recovery token: ${recoveryError.message}` },
    { status: 500 },
  );
}

// Change password
const { error: updateError } = await client.auth.updateUser({
  password: bodyPayload.password,
});
if (updateError) {
  return NextResponse.json(
    { message: `Failed to change password: ${updateError.message}` },
    { status: 500 },
  );
}


Problematic case:

* User enters a correct OTP
* But enters an invalid new password (e.g. same as old password, fails policy, etc.)
*
updateUser
updateUser
fails
* The OTP is now burned
* User must wait X minutes and request a new code, even though the OTP itself was valid

This feels like a bad UX because a password validation error permanently consumes a valid recovery token.

Questions:

* Is this expected behavior with Supabase OTP recovery?
* Is there a recommended way to avoid burning the OTP before password validation?
* Should password validation be done before calling
verifyOtp
verifyOtp
?
* Or is the intended solution to re-issue a new recovery OTP if
updateUser
updateUser
fails?

Basically, how do you handle OTP verification errors vs password validation errors without locking users out unnecessarily?

Any best-practice guidance would be appreciated.
Supabase banner
SupabaseJoin
Supabase gives you the tools, documentation, and community that makes managing databases, authentication, and backend infrastructure a lot less overwhelming.
45,816Members
Resources
Was this page helpful?

Similar Threads

Recent Announcements

Similar Threads

Confused about expected auth flow in nextjs supabase template
SupabaseSSupabase / help-and-questions
5mo ago
supabase OTP auth with non-Twillio vendor?
SupabaseSSupabase / help-and-questions
3y ago
Question about using native PostgreSQL roles with Supabase Auth
SupabaseSSupabase / help-and-questions
4mo ago
Supabase auth email otp wont send to users
SupabaseSSupabase / help-and-questions
7mo ago