{"record":{"id":"7267d9b93efb8c3f","repo":"plandex-ai/plandex","slug":"error-validating-org-membership-err-error","errorCode":null,"errorMessage":"Error validating org membership: {err.Error()}","messagePattern":"Error validating org membership: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/users.go","lineNumber":153,"sourceCode":"\t\thttp.Error(w, \"Error getting org user: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\t// ensure current user can remove target user\n\tremovePermission := shared.Permission(strings.Join([]string{string(shared.PermissionRemoveUser), orgUser.OrgRoleId}, \"|\"))\n\n\tif !auth.HasPermission(removePermission) {\n\t\tlog.Printf(\"User does not have permission to remove user with role: %v\\n\", orgUser.OrgRoleId)\n\t\thttp.Error(w, \"User does not have permission to remove user with role: \"+orgUser.OrgRoleId, http.StatusForbidden)\n\t\treturn\n\t}\n\n\t// verify user is org member\n\tisMember, err := db.ValidateOrgMembership(userId, auth.OrgId)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error validating org membership: %v\\n\", err)\n\t\thttp.Error(w, \"Error validating org membership: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tif !isMember {\n\t\tlog.Printf(\"User %s is not a member of org %s\\n\", userId, auth.OrgId)\n\t\thttp.Error(w, \"User \"+userId+\" is not a member of org \"+auth.OrgId, http.StatusForbidden)\n\t\treturn\n\t}\n\n\torgOwnerRoleId, err := db.GetOrgOwnerRoleId()\n\n\tif err != nil {\n\t\tlog.Printf(\"Error getting org owner role id: %v\\n\", err)\n\t\thttp.Error(w, \"Error getting org owner role id: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\t// verify user isn't the only org owner","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/users.go#L135-L171","documentation":"db.ValidateOrgMembership(userId, auth.OrgId) returned an error while checking that the target user belongs to the caller's org. This is a DB-level failure (connection, query, or scan), reported as HTTP 500 with the raw error text — distinct from isMember=false, which yields a 403.","triggerScenarios":"ValidateOrgMembership errors out — DB connection drop mid-request, table/index missing after a migration, or the query times out under load.","commonSituations":"Postgres restarted or connection pool exhausted during the request; migration rolled the org_users table back; read replica lag or failover in the middle of the call.","solutions":["Check server logs for the wrapped error to identify connection vs schema vs timeout causes","Verify DB connectivity and pool health (max connections, idle timeouts)","Confirm the org_users table schema and migrations are intact","Retry the request if the failure was transient (connection blip)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if err := db.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"database unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"isMember, err := db.ValidateOrgMembership(userId, auth.OrgId)\nif err != nil {\n    if isTransientDBError(err) {\n        http.Error(w, \"temporarily unavailable, retry\", http.StatusServiceUnavailable)\n    } else {\n        http.Error(w, \"internal error\", http.StatusInternalServerError)\n    }\n    return\n}","preventionTips":["Configure sane connection-pool sizes and idle timeouts for the DB driver","Add retry-with-backoff for transient DB errors (driver.ErrBadConn, context deadline)","Run migrations before deploy and smoke-check the org_users table","Alert on DB error rates from handler logs"],"tags":["go","database","connectivity","http-500"],"backgroundTag":"database-query-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}