Background
While building an internal e-commerce site, I put an email required constraint on the registration form from day one. The reason was simple: authentication = email was my unconscious assumption.
Then reality hit. Most existing users only had phone numbers. Specifically, users registered via LINE only had phone numbers in the database — no email addresses. When they tried to register, they got a Bad Request error.
The Problem Structure
The frontend (React) sends phone number + password. The backend (Node.js/TypeScript) looks up users by phone number, but users with email as required field = unset were not processed correctly.
Worse, when a phone number was submitted for new registration but already existed in the DB, it tried to create a new record and hit a Unique constraint violation.
Two problems:
- Registration: email as required field causes validation to reject phone-only users
- Registration: attempting to create a new user with an existing phone number causes Unique error
Solution
Frontend Changes
Made the email field optional. Removed required attribute and updated the placeholder.
<input
type="email"
placeholder="Email (optional)"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
Backend Changes
Unified login/registration logic to accept phone OR email.
// Before: search by email only
const user = await User.findOne({ where: { email } });
// After: search by phone OR email
const user = await User.findOne({
where: {
[Op.or]: [
phone ? { phone } : null,
email ? { email } : null,
].filter(Boolean),
},
});
Added logic to route existing phone numbers to login instead of registration:
if (existingUser) {
return handleLogin(existingUser, password);
} else {
return handleRegister({ phone, email, password });
}
Lessons Learned
Question the assumption that email = primary identifier. In Asia and Southeast Asia, phone numbers are often the primary identifier. This is especially true for LINE or WhatsApp-based businesses.
Do not over-separate registration and login. When these are completely separate APIs, edge cases like phone number exists but the user does not know become hard to handle.
Summary
- Match auth fields to user reality — use OR not AND
- Keep frontend validation and backend validation in sync
- Existing user registration error is a sign of a design assumption mismatch
What looked like a small bug fix revealed a deeper design flaw about what a user really is. Code that matches reality beats code that merely runs correctly.
Top comments (0)