plandex-ai/plandex · warning

user already exists for email: %v

Error message

user already exists for email: %v

What it means

CreateUser inserts into the users table with email as a unique key; when the DB rejects the insert with a unique-constraint violation, IsNonUniqueErr detects it and this error is returned instead of exposing the raw DB error.

Source

Thrown at app/server/db/user_helpers.go:149

func CreateUser(name, email string, tx *sqlx.Tx) (*User, error) {
	emailSplit := strings.Split(email, "@")
	if len(emailSplit) != 2 {
		return nil, fmt.Errorf("invalid email: %v", email)
	}
	domain := emailSplit[1]

	user := User{
		Name:   name,
		Email:  email,
		Domain: domain,
	}

	err := tx.QueryRow("INSERT INTO users (name, email, domain) VALUES ($1, $2, $3) RETURNING id", user.Name, user.Email, user.Domain).Scan(&user.Id)

	if err != nil {
		if IsNonUniqueErr(err) {
			return nil, fmt.Errorf("user already exists for email: %v", email)
		}
		return nil, fmt.Errorf("error creating user: %v", err)
	}

	return &user, nil
}

func NumUsersWithRole(orgId, roleId string) (int, error) {
	var count int
	err := Conn.Get(&count, "SELECT COUNT(*) FROM orgs_users WHERE org_id = $1 AND org_role_id = $2", orgId, roleId)

	if err != nil {
		return 0, fmt.Errorf("error counting users with role: %v", err)
	}

	return count, nil
}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check for an existing user with GetUser/lookup by email before calling CreateUser
  2. Catch this error and return a friendly 'account already exists, sign in instead' response (e.g. HTTP 409)
  3. Route the user to the sign-in or password-reset flow
  4. If accounts were partially created in the same tx, rely on the surrounding WithTx rollback and surface the conflict

Example fix

// before
user, err := db.CreateUser(name, email, tx)
// after
user, err := db.CreateUser(name, email, tx)
if err != nil && strings.HasPrefix(err.Error(), "user already exists") { return nil, ErrEmailTaken } // map to 409/sign-in prompt
Defensive patterns

Strategy: validation

Validate before calling

var existing User
err := tx.Get(&existing, "SELECT id FROM users WHERE email = $1", email)
if err == nil { return ErrEmailTaken } // check before insert
if err != sql.ErrNoRows { return err }

Type guard

func isDuplicateUserErr(err error) bool { return strings.HasPrefix(err.Error(), "user already exists for email") }

Try / catch

user, err := db.CreateUser(name, email, tx)
if err != nil {
    if isDuplicateUserErr(err) { return nil, ErrEmailTaken } // map to 409 / sign-in redirect
    return nil, err
}

Prevention

When it happens

Trigger: Calling CreateUser (via CreateAccount) with an email that already has a row in the users table, causing the unique index on email to reject the INSERT.

Common situations: Duplicate sign-up with the same email, user retrying a completed registration, two concurrent sign-ups racing on the same email, or reusing an email from an old account.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/01235450894d6e85. Report an issue: GitHub.