mem0ai/mem0 · warning · HTTPException

Email is already in use.

Error message

Email is already in use.

What it means

Raised by PATCH /auth/me when the requested new email already belongs to a different account (select User where email = body.email and id != current user). Email is unique across users, so a profile update that would transfer an email owned by another row is rejected with 409 before any commit.

Source

Thrown at server/routers/auth.py:190

@router.patch("/me", response_model=UserResponse)
def update_me(
    body: UpdateProfileRequest,
    user: User = Depends(require_auth),
    db: Session = Depends(get_db),
):
    # require_auth resolves the user in its own short-lived session, so `user` is
    # detached from this request's `db`. Load a session-managed copy to mutate.
    db_user = db.get(User, user.id)
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found.")

    if body.name is not None and body.name.strip():
        db_user.name = body.name.strip()

    if body.email is not None and body.email != db_user.email:
        collision = db.scalar(select(User).where(User.email == body.email, User.id != db_user.id))
        if collision is not None:
            raise HTTPException(status_code=409, detail="Email is already in use.")
        db_user.email = body.email

    db.commit()
    return db_user


@router.post("/change-password", response_model=MessageResponse)
def change_password(
    body: ChangePasswordRequest,
    user: User = Depends(require_auth),
    db: Session = Depends(get_db),
):
    # require_auth resolves the user in its own short-lived session, so `user` is
    # detached from this request's `db`. Load a session-managed copy to mutate.
    db_user = db.get(User, user.id)
    if db_user is None or not verify_password(body.current_password, db_user.password_hash):
        raise HTTPException(status_code=401, detail="Current password is incorrect.")

View on GitHub (pinned to 001c235229)

Solutions

  1. Choose a different email address, or first change/release the email on the account that currently owns it
  2. If the user owns both accounts, log into the other account and change its email (or delete that account), then retry
  3. Operators: if this blocks a legitimate merge, rename the other account's email out of the way in the DB before retrying

Example fix

// before
await patch("/auth/me", { email: "shared@team.com" }); // 409 if owned by another user

// after
// free the email on its current owner first, then apply
await patch("/auth/me", { email: "shared@team.com" }); // succeeds once the other account no longer holds it
Defensive patterns

Strategy: validation

Validate before calling

// client-side duplicate check (best effort; server remains authoritative)
const taken = await fetch(`/auth/users?email=${encodeURIComponent(newEmail)}`).then(r => r.ok);
if (taken) showEmailInUseError();

Try / catch

catch (e) {
  if (e.status === 409 && e.detail === "Email is already in use.") {
    showFieldError("email", "This email belongs to another account.");
    return; // keep form open, do not re-submit unchanged
  }
  throw e;
}

Prevention

When it happens

Trigger: PATCH /auth/me with {"email": "x@y.z"} where x@y.z is registered to another user; a user trying to change email to one they registered earlier on a second account; case-sensitive lookup matching an existing row (depending on collation, exact-match here).

Common situations: User has two accounts and wants to move the primary email to the current one; typo leads to an already-registered address; team SSO where a colleague's email is entered by mistake.

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/07f3b923684f95e9. Report an issue: GitHub.