antiwork/gumroad · error · VerificationError
deleted_user
deleted_user
Error message
deleted_user
What it means
Raised in `Logins::PasskeysController#create` (logins/passkeys_controller.rb:24): the WebAuthn assertion fully verified (signature, challenge, sign count all valid) and resolved to a stored `WebauthnCredential`, but that credential's user is soft-deleted (`user.deleted?`). Gumroad keeps passkey rows after account deletion, so authentication is refused at the last step with the generic 422 error message.
Source
Thrown at app/controllers/logins/passkeys_controller.rb:24
AUTHENTICATION_ERROR_MESSAGE = "We couldn't sign you in with that passkey. Please try again or use your password."
skip_before_action :check_suspended
skip_before_action :invalidate_session_if_necessary
def options
render json: { success: true, options: build_webauthn_authentication_options }
end
def create
Rails.logger.info("passkey.authentication.started")
challenge = session.delete(AUTHENTICATION_CHALLENGE_SESSION_KEY)
raise VerificationError, "missing_challenge" if challenge.blank?
stored_credential = verified_credential(challenge)
user = stored_credential.user
raise VerificationError, "deleted_user" if user.deleted?
stored_credential.save!
user.remember_me = true
sign_in(user)
reset_two_factor_auth_login_session
merge_guest_cart_with_user_cart
refresh_passkey_setup_prompt(user)
Rails.logger.info("passkey.authentication.succeeded user_id=#{user.id} webauthn_credential_id=#{stored_credential.id}")
render json: { success: true, redirect_location: login_path_for(user) }
rescue VerificationError => e
log_authentication_failure(e.reason)
render json: { success: false, error_message: AUTHENTICATION_ERROR_MESSAGE }, status: :unprocessable_entity
end
privateView on GitHub (pinned to afeacbd394)
Solutions
- If the account should exist, restore/undelete the user (support action) — the same passkey will then work again.
- If the account is intentionally gone, sign in flow should guide to account recovery/creation rather than passkey retry; retrying cannot succeed.
- On account deletion flows, consider destroying webauthn_credentials so deleted users' passkeys never surface in browser autofill.
- Frontend: treat the 422 as terminal for this credential and fall back to password/other methods, not a retry.
Example fix
# before — deletion leaves the passkey behind, login later fails opaquely user.destroy # soft delete; webauthn_credentials remain # after — remove credentials when the account is deleted user.destroy user.webauthn_credentials.destroy_all
Defensive patterns
Strategy: try-catch
Try / catch
begin
user = stored_credential.user
raise VerificationError, "deleted_user" if user.deleted?
rescue VerificationError => e
log_authentication_failure(e.reason)
render json: { success: false, error_message: AUTHENTICATION_ERROR_MESSAGE }, status: :unprocessable_entity
end Prevention
- Treat the 422 as terminal for this credential — offer password/recovery sign-in, not retry.
- Destroy webauthn_credentials on account deletion so stale passkeys leave browser autofill.
- Surface a distinct in-product message for deleted accounts at the sign-in entry point when email is known.
- Keep the reason in server logs (reason=deleted_user) for support triage.
When it happens
Trigger: A user with a registered passkey deletes their Gumroad account and later tries passkey login; an admin deletes/deactivates the account while its passkey remains stored; the credential was registered to an account that was subsequently removed in moderation.
Common situations: Returning users after account deletion attempts; shared devices where an old account's passkey still surfaces in the browser's autofill; automated tests exercising deleted-user login paths.
Related errors
- We couldn't sign you in with that passkey. Please try again
- missing_challenge
- unknown_credential
- Could not add this passkey. Please try again.
- Sorry, something went wrong. Please try again.
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/48d74e942080f60b.
Report an issue: GitHub.