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
- 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
- Verify the orgRoleId exists in org_roles (fetch via GetOrgOwnerRoleId/GetOrgMemberRoleId) before inserting
- Verify orgId and userId reference existing rows in orgs and users
- 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
- Use INSERT ... ON CONFLICT ON CONSTRAINT org_user_unique DO NOTHING for idempotent membership
- Always source orgRoleId from GetOrgOwnerRoleId/GetOrgMemberRoleId, never hard-code
- Validate org and user ids exist before inserting
- Run within a transaction to avoid duplicate-insert races
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
- error adding org user: %v
- error adding plan context tokens: %v
- error listing org roles: %v
- error getting plan config: %v
- error storing plan config: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/258410f66b7c9782.
Report an issue: GitHub.