[GH-ISSUE #9183] tracking: email/OTP pipeline (error surfacing, Prisma v7 regressions) #28624

Open
opened 2026-04-17 20:03:21 -05:00 by GiteaMirror · 0 comments
Owner

Originally created by @gustavovalverde on GitHub (Apr 14, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/9183

Summary

The email and OTP pipeline shows two recurring failure patterns. Errors thrown inside sendVerificationOTP or sendVerificationEmail can be swallowed by background execution and still return HTTP 200. Prisma v7 adapter behavior can also corrupt verification records because cleanup and lookup paths still assume uniqueness that the schema does not provide.

Root cause

The send pipeline catches and hides failures in the background-task runner, so callers do not receive the original APIError status or payload. The response body can also be disturbed after the response is sent, and toOTPIdentifier() does not normalize case. signIn.emailOtp also does not expose a metadata parameter. In the Prisma v7 adapter path, verification.delete() and related queries still target a non-unique identifier shape, which breaks update, change-email, and OTP verification cleanup.

Scope

In: error propagation from email/OTP send paths, case normalization on email OTP, Prisma v7 adapter verification-record lookup and delete.

Out: email-change ceremony (see link-only email-change thread). sendVerificationEmail behaviour when user is already verified (link-only email-change). Phone plugin parity (outside any cluster; see standalones #6943, #8042).

Resolution criteria

  • Errors thrown in sendVerificationOTP / sendVerificationEmail surface to the caller with the original status and payload.
  • Email OTP lookups are case-insensitive.
  • signIn.emailOtp accepts a metadata parameter.
  • Prisma v7 updateUser, changeEmail, and OTP verification persist and cleanup verification rows correctly.
  • Prior closed context: #6267 (Prisma P2025 on verification delete), #7696 (USER_NOT_FOUND thrown), #6644, #6436, #8670.
  • Members moved out to standalone: #4262 (magic-link URL generator), #6943 (phone/email OTP API parity).
Originally created by @gustavovalverde on GitHub (Apr 14, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/9183 ## Summary The email and OTP pipeline shows two recurring failure patterns. Errors thrown inside `sendVerificationOTP` or `sendVerificationEmail` can be swallowed by background execution and still return HTTP 200. Prisma v7 adapter behavior can also corrupt `verification` records because cleanup and lookup paths still assume uniqueness that the schema does not provide. ## Root cause The send pipeline catches and hides failures in the background-task runner, so callers do not receive the original `APIError` status or payload. The response body can also be disturbed after the response is sent, and `toOTPIdentifier()` does not normalize case. `signIn.emailOtp` also does not expose a `metadata` parameter. In the Prisma v7 adapter path, `verification.delete()` and related queries still target a non-unique `identifier` shape, which breaks update, change-email, and OTP verification cleanup. ## Scope **In:** error propagation from email/OTP send paths, case normalization on email OTP, Prisma v7 adapter verification-record lookup and delete. **Out:** email-change ceremony (see link-only email-change thread). `sendVerificationEmail` behaviour when user is already verified (link-only email-change). Phone plugin parity (outside any cluster; see standalones #6943, #8042). ## Resolution criteria - Errors thrown in `sendVerificationOTP` / `sendVerificationEmail` surface to the caller with the original status and payload. - Email OTP lookups are case-insensitive. - `signIn.emailOtp` accepts a `metadata` parameter. - Prisma v7 `updateUser`, `changeEmail`, and OTP verification persist and cleanup verification rows correctly. ## Related - Prior closed context: #6267 (Prisma P2025 on verification delete), #7696 (USER_NOT_FOUND thrown), #6644, #6436, #8670. - Members moved out to standalone: #4262 (magic-link URL generator), #6943 (phone/email OTP API parity).
GiteaMirror added the trackingcredentialsdatabasebug labels 2026-04-17 20:03:21 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#28624