plandex-ai/plandex · error

error adding org member: %v

Error message

error adding org member: %v

What it means

CreateOrgUser wraps any failure of the INSERT INTO orgs_users (org_id, user_id, org_role_id) statement with this message. It fires when the INSERT itself fails — most commonly a duplicate (org_id,user_id) row violating the org_user_unique constraint, a missing org_role_id foreign key, or a DB connection error.

Source

Thrown at app/server/db/org_helpers.go:203

	if err != nil {
		return fmt.Errorf("error deleting org member: %v", err)
	}

	return nil
}

func CreateOrgUser(orgId, userId, orgRoleId string, tx *sqlx.Tx) error {
	query := "INSERT INTO orgs_users (org_id, user_id, org_role_id) VALUES ($1, $2, $3)"
	var err error
	if tx == nil {
		_, err = Conn.Exec(query, orgId, userId, orgRoleId)
	} else {
		_, err = tx.Exec(query, orgId, userId, orgRoleId)
	}

	if err != nil {
		return fmt.Errorf("error adding org member: %v", err)
	}

	return nil
}

func ListOrgRoles(orgId string) ([]*OrgRole, error) {
	var orgRoles []*OrgRole
	err := Conn.Select(&orgRoles, "SELECT * FROM org_roles WHERE org_id IS NULL OR org_id = $1", orgId)

	if err != nil {
		return nil, fmt.Errorf("error listing org roles: %v", err)
	}

	return orgRoles, nil
}

func AddToOrgForDomain(userId, domain string, tx *sqlx.Tx) (string, error) {
	org, err := GetOrgForDomain(domain)

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check the wrapped cause in the %v output: 'duplicate key value violates unique constraint "org_user_unique"' means the user is already a member — treat as success or use an ON CONFLICT DO NOTHING clause like AddUsersToOrgForDomain does
  2. Verify the orgRoleId exists in org_roles (fetch via GetOrgOwnerRoleId/GetOrgMemberRoleId) before inserting
  3. Verify orgId and userId reference existing rows in orgs and users
  4. If the DB connection failed, check DATABASE_URL connectivity and retry after the pool recovers

Example fix

// before
err = CreateOrgUser(org.Id, userId, orgOwnerRoleId, tx)
// after: tolerate existing membership
query := "INSERT INTO orgs_users (org_id, user_id, org_role_id) VALUES ($1, $2, $3) ON CONFLICT ON CONSTRAINT org_user_unique DO NOTHING"
Defensive patterns

Strategy: validation

Validate before calling

// check membership before inserting
var exists bool
err := Conn.Get(&exists, "SELECT EXISTS(SELECT 1 FROM orgs_users WHERE org_id=$1 AND user_id=$2)", orgId, userId)
if err == nil && exists {
    return nil // already a member
}
// also: rows, _ := Conn.Queryx("SELECT id FROM org_roles WHERE id=$1", orgRoleId); ensure role exists

Type guard

func orgRoleExists(roleId string) (bool, error) {
	var ok bool
	err := Conn.Get(&ok, "SELECT EXISTS(SELECT 1 FROM org_roles WHERE id=$1)", roleId)
	return ok, err
}

Try / catch

if err := CreateOrgUser(orgId, userId, roleId, tx); err != nil {
    if strings.Contains(err.Error(), "org_user_unique") {
        return nil // idempotent: already a member
    }
    return fmt.Errorf("adding org member %s to %s: %w", userId, orgId, err)
}

Prevention

When it happens

Trigger: Calling CreateOrgUser with (a) a user already in the org (unique constraint violation on orgs_users), (b) an invalid orgRoleId that doesn't exist in org_roles (FK violation), (c) an invalid orgId or userId, or (d) the database connection is down.

Common situations: Auto-adding a user to a domain-matched org when the user already exists as a member; passing a role id from a different org; race where two requests add the same user concurrently; stale DB credentials or a restarted Postgres.

Related errors


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