Members are told when their passcode email is rejected
Shipped 2026-09-11
TUN-859 made email send failures visible in Datadog. This makes them visible to the member, who is the person actually locked out.
sendEmailPasscode() called sendPasscodeToEmail() without awaiting it and
then returned status: true with “passcode sent to (ca***@l***.net)”. A member
whose address had just bounced was told their code was on its way to a specific
mailbox, waited, retried, and was told exactly the same thing again.
sendPasscodeToEmail() compounded it by logging passcode.sent whatever
happened, so the record asserted a delivery that had not taken place either.
Four real cases turned up in the first two days of TUN-859’s reporting, across two members, every one a soft bounce.
The send is now awaited, and a rejection returns a verdict the login screen can act on: the reason, whether it was transient, and what this member can do instead. A member with a verified phone is offered the code by SMS. A member without one is told plainly that there is no second channel on their account.
sendPhonePasscode() has always checked its result and returned a failure — this
brings the email path into line with its sibling rather than inventing a pattern.
Why security questions are not offered
They were built and removed. Security questions lead only to a password reset, and the member’s password is fine in this situation — it is their second factor that is broken. Following that route ends at the same failing passcode step, so it is a loop rather than a way in. A genuine last-resort access route is being worked on separately.
Found along the way
Ten logger.info and logger.warn calls in the passcode service used a message:
key. Winston hoists that key out of the object it is given and leaves the remaining
fields to be appended as a second line, so every field those calls were written to
record was reaching Datadog detached from its label. They now use event:, which
keeps the object intact. Twelve more calls elsewhere have the same fault, tracked
as TUN-868.