diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/UserAlreadyExistsException.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/UserAlreadyExistsException.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8bd0a27961a2af8079fdbae05264fcac2038806
--- /dev/null
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/UserAlreadyExistsException.java
@@ -0,0 +1,85 @@
+/*
+ ************************************************************************
+ *******************  CANADIAN ASTRONOMY DATA CENTRE  *******************
+ **************  CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES  **************
+ *
+ *  (c) 2015.                            (c) 2015.
+ *  Government of Canada                 Gouvernement du Canada
+ *  National Research Council            Conseil national de recherches
+ *  Ottawa, Canada, K1A 0R6              Ottawa, Canada, K1A 0R6
+ *  All rights reserved                  Tous droits réservés
+ *
+ *  NRC disclaims any warranties,        Le CNRC dénie toute garantie
+ *  expressed, implied, or               énoncée, implicite ou légale,
+ *  statutory, of any kind with          de quelque nature que ce
+ *  respect to the software,             soit, concernant le logiciel,
+ *  including without limitation         y compris sans restriction
+ *  any warranty of merchantability      toute garantie de valeur
+ *  or fitness for a particular          marchande ou de pertinence
+ *  purpose. NRC shall not be            pour un usage particulier.
+ *  liable in any event for any          Le CNRC ne pourra en aucun cas
+ *  damages, whether direct or           être tenu responsable de tout
+ *  indirect, special or general,        dommage, direct ou indirect,
+ *  consequential or incidental,         particulier ou général,
+ *  arising from the use of the          accessoire ou fortuit, résultant
+ *  software.  Neither the name          de l'utilisation du logiciel. Ni
+ *  of the National Research             le nom du Conseil National de
+ *  Council of Canada nor the            Recherches du Canada ni les noms
+ *  names of its contributors may        de ses  participants ne peuvent
+ *  be used to endorse or promote        être utilisés pour approuver ou
+ *  products derived from this           promouvoir les produits dérivés
+ *  software without specific prior      de ce logiciel sans autorisation
+ *  written permission.                  préalable et particulière
+ *                                       par écrit.
+ *
+ *  This file is part of the             Ce fichier fait partie du projet
+ *  OpenCADC project.                    OpenCADC.
+ *
+ *  OpenCADC is free software:           OpenCADC est un logiciel libre ;
+ *  you can redistribute it and/or       vous pouvez le redistribuer ou le
+ *  modify it under the terms of         modifier suivant les termes de
+ *  the GNU Affero General Public        la “GNU Affero General Public
+ *  License as published by the          License” telle que publiée
+ *  Free Software Foundation,            par la Free Software Foundation
+ *  either version 3 of the              : soit la version 3 de cette
+ *  License, or (at your option)         licence, soit (à votre gré)
+ *  any later version.                   toute version ultérieure.
+ *
+ *  OpenCADC is distributed in the       OpenCADC est distribué
+ *  hope that it will be useful,         dans l’espoir qu’il vous
+ *  but WITHOUT ANY WARRANTY;            sera utile, mais SANS AUCUNE
+ *  without even the implied             GARANTIE : sans même la garantie
+ *  warranty of MERCHANTABILITY          implicite de COMMERCIALISABILITÉ
+ *  or FITNESS FOR A PARTICULAR          ni d’ADÉQUATION À UN OBJECTIF
+ *  PURPOSE.  See the GNU Affero         PARTICULIER. Consultez la Licence
+ *  General Public License for           Générale Publique GNU Affero
+ *  more details.                        pour plus de détails.
+ *
+ *  You should have received             Vous devriez avoir reçu une
+ *  a copy of the GNU Affero             copie de la Licence Générale
+ *  General Public License along         Publique GNU Affero avec
+ *  with OpenCADC.  If not, see          OpenCADC ; si ce n’est
+ *  <http://www.gnu.org/licenses/>.      pas le cas, consultez :
+ *                                       <http://www.gnu.org/licenses/>.
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.ac;
+
+public class UserAlreadyExistsException extends Exception
+{
+    /**
+     * Constructs a new exception with the specified detail message.  The
+     * cause is not initialized, and may subsequently be initialized by
+     * a call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public UserAlreadyExistsException(String message)
+    {
+        super(message);
+    }
+}
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java
index af5a6c53cdeabe0bcaed87643e93187f75ada658..599f98586cf90640981da00f41f525f23974745e 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java
@@ -73,6 +73,7 @@ import java.security.Principal;
 import java.util.Collection;
 
 import ca.nrc.cadc.ac.User;
+import ca.nrc.cadc.ac.UserAlreadyExistsException;
 import ca.nrc.cadc.ac.UserNotFoundException;
 import ca.nrc.cadc.ac.UserRequest;
 import ca.nrc.cadc.net.TransientException;
@@ -102,7 +103,8 @@ public interface UserPersistence<T extends Principal>
      * @throws AccessControlException If the operation is not permitted.
      */
     User<T> addUser(UserRequest<T> user)
-        throws TransientException, AccessControlException;
+        throws TransientException, AccessControlException,
+               UserAlreadyExistsException;
     
     /**
      * Get the user specified by userID.
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java
index 90005ee0beacce22d0dda20116a1d06e60733128..1b85d39d0a180638f3d53bb03b21449960f35d7f 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java
@@ -68,6 +68,7 @@
  */
 package ca.nrc.cadc.ac.server.ldap;
 
+import ca.nrc.cadc.ac.UserAlreadyExistsException;
 import ca.nrc.cadc.auth.HttpPrincipal;
 import ca.nrc.cadc.auth.NumericPrincipal;
 import ca.nrc.cadc.auth.OpenIdPrincipal;
@@ -78,6 +79,8 @@ import com.unboundid.ldap.sdk.LDAPException;
 import com.unboundid.ldap.sdk.ResultCode;
 import com.unboundid.ldap.sdk.SearchResult;
 import com.unboundid.ldap.sdk.SearchScope;
+
+import java.nio.file.FileAlreadyExistsException;
 import java.security.AccessControlException;
 import java.security.AccessController;
 import java.security.GeneralSecurityException;
@@ -233,7 +236,7 @@ public abstract class LdapDAO
             throws TransientException
     {
     	logger.debug("Ldap result: " + code);
-    	
+
         if (code == ResultCode.INSUFFICIENT_ACCESS_RIGHTS)
         {
             throw new AccessControlException("Not authorized ");
@@ -242,8 +245,7 @@ public abstract class LdapDAO
         {
             throw new AccessControlException("Invalid credentials ");
         }
-        else if ((code == ResultCode.SUCCESS) || (code
-                                                  == ResultCode.NO_SUCH_OBJECT))
+        else if ((code == ResultCode.SUCCESS) || (code == ResultCode.NO_SUCH_OBJECT))
         {
             // all good. nothing to do
         }
@@ -251,8 +253,7 @@ public abstract class LdapDAO
         {
             throw new IllegalArgumentException("Error in Ldap parameters ");
         }
-        else if (code == ResultCode.BUSY ||
-                 code == ResultCode.CONNECT_ERROR)
+        else if (code == ResultCode.BUSY || code == ResultCode.CONNECT_ERROR)
         {
             throw new TransientException("Connection problems ");
         }
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java
index 956661a42e45a71aa4b55e4fc1f3f3bfa2d2ebf0..835fa9a9924abb5cc2d919979761336bed1d8da6 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java
@@ -96,6 +96,7 @@ import java.util.Map;
 import javax.security.auth.x500.X500Principal;
 import org.apache.log4j.Logger;
 
+
 public class LdapUserDAO<T extends Principal> extends LdapDAO
 {
     private static final Logger logger = Logger.getLogger(LdapUserDAO.class);
@@ -126,17 +127,19 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
     protected static final String LDAP_GID_NUMBER = "gidNumber";
     protected static final String LDAP_HOME_DIRECTORY = "homeDirectory";
     protected static final String LDAP_LOGIN_SHELL = "loginShell";
-    
+
     private String[] userAttribs = new String[]
-    {
-        LDAP_FIRST_NAME, LDAP_LAST_NAME, LDAP_ADDRESS, LDAP_CITY, LDAP_COUNTRY,
-        LDAP_EMAIL, LDAP_INSTITUTE, LDAP_UID, LDAP_UID_NUMBER, LDAP_GID_NUMBER,
-        LDAP_HOME_DIRECTORY, LDAP_LOGIN_SHELL
-    };
+            {
+                    LDAP_FIRST_NAME, LDAP_LAST_NAME, LDAP_ADDRESS, LDAP_CITY,
+                    LDAP_COUNTRY,
+                    LDAP_EMAIL, LDAP_INSTITUTE, LDAP_UID, LDAP_UID_NUMBER,
+                    LDAP_GID_NUMBER,
+                    LDAP_HOME_DIRECTORY, LDAP_LOGIN_SHELL
+            };
     private String[] memberAttribs = new String[]
-    {
-        LDAP_FIRST_NAME, LDAP_LAST_NAME
-    };
+            {
+                    LDAP_FIRST_NAME, LDAP_LAST_NAME
+            };
 
     public LdapUserDAO(LdapConfig config)
     {
@@ -159,23 +162,22 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
                          memberAttribs.length);
         memberAttribs = tmp;
     }
-    
+
     /**
-     * 
      * @return
-     * @throws TransientException 
+     * @throws TransientException
      */
     public Collection<HttpPrincipal> getCadcIDs() throws TransientException
     {
         try
         {
             Filter filter = Filter.createPresenceFilter("uid");
-            String [] attributes = new String[] {"uid"};
-            
-            SearchRequest searchRequest = 
-                    new SearchRequest(config.getUsersDN(), 
+            String[] attributes = new String[]{"uid"};
+
+            SearchRequest searchRequest =
+                    new SearchRequest(config.getUsersDN(),
                                       SearchScope.SUB, filter, attributes);
-    
+
             SearchResult searchResult = null;
             try
             {
@@ -189,24 +191,24 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
                     throw new IllegalStateException("Could not find users root");
                 }
             }
-            
+
             LdapDAO.checkLdapResult(searchResult.getResultCode());
             Collection<HttpPrincipal> userIDs = new HashSet<HttpPrincipal>();
             for (SearchResultEntry next : searchResult.getSearchEntries())
             {
                 userIDs.add(new HttpPrincipal(next.getAttributeValue("uid")));
             }
-            
+
             return userIDs;
         }
         catch (LDAPException e1)
         {
             logger.debug("getCadcIDs Exception: " + e1, e1);
             LdapDAO.checkLdapResult(e1.getResultCode());
-            throw new IllegalStateException("Unexpected exception: " + 
-                    e1.getMatchedDN(), e1);
+            throw new IllegalStateException("Unexpected exception: " +
+                                            e1.getMatchedDN(), e1);
         }
-        
+
     }
 
 
@@ -215,20 +217,22 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
      *
      * @param userRequest The user to add.
      * @return User instance.
-     * @throws TransientException     If an temporary, unexpected problem occurred.
-     * @throws AccessControlException If the operation is not permitted.
+     * @throws TransientException         If an temporary, unexpected problem occurred.
+     * @throws AccessControlException     If the operation is not permitted.
+     * @throws UserAlreadyExistsException If the user already exists.
      */
     public User<T> addUser(final UserRequest<T> userRequest)
-        throws TransientException
+            throws TransientException, UserAlreadyExistsException
     {
         final User<T> user = userRequest.getUser();
         final Class userType = user.getUserID().getClass();
-        String searchField = userLdapAttrib.get(userType);
+        final String searchField = userLdapAttrib.get(userType);
+
         if (searchField == null)
         {
             throw new IllegalArgumentException("Unsupported principal type " + userType);
         }
-        
+
         try
         {
             // add new user
@@ -236,16 +240,20 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
             List<Attribute> attributes = new ArrayList<Attribute>();
             addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_INET_ORG_PERSON);
             addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_CADC_ACCOUNT);
-            addAttribute(attributes, LDAP_COMMON_NAME, user.getUserID().getName());
-            addAttribute(attributes, LDAP_DISTINGUISHED_NAME, userDN.toNormalizedString());
-            addAttribute(attributes, LADP_USER_PASSWORD, userRequest.getPassword());
+            addAttribute(attributes, LDAP_COMMON_NAME, user.getUserID()
+                    .getName());
+            addAttribute(attributes, LDAP_DISTINGUISHED_NAME, userDN
+                    .toNormalizedString());
+            addAttribute(attributes, LADP_USER_PASSWORD, userRequest
+                    .getPassword());
 
             for (UserDetails details : user.details)
             {
                 if (details.getClass() == PersonalDetails.class)
                 {
                     PersonalDetails pd = (PersonalDetails) details;
-                    addAttribute(attributes, LDAP_FIRST_NAME, pd.getFirstName());
+                    addAttribute(attributes, LDAP_FIRST_NAME, pd
+                            .getFirstName());
                     addAttribute(attributes, LDAP_LAST_NAME, pd.getLastName());
                     addAttribute(attributes, LDAP_ADDRESS, pd.address);
                     addAttribute(attributes, LDAP_CITY, pd.city);
@@ -257,14 +265,18 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
                 {
                     PosixDetails pd = (PosixDetails) details;
                     addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_POSIX_ACCOUNT);
-                    addAttribute(attributes, LDAP_UID, Long.toString(pd.getUid()));
-                    addAttribute(attributes, LDAP_UID_NUMBER, Long.toString(pd.getUid()));
-                    addAttribute(attributes, LDAP_GID_NUMBER, Long.toString(pd.getGid()));
-                    addAttribute(attributes, LDAP_HOME_DIRECTORY, pd.getHomeDirectory());
+                    addAttribute(attributes, LDAP_UID, Long
+                            .toString(pd.getUid()));
+                    addAttribute(attributes, LDAP_UID_NUMBER, Long
+                            .toString(pd.getUid()));
+                    addAttribute(attributes, LDAP_GID_NUMBER, Long
+                            .toString(pd.getGid()));
+                    addAttribute(attributes, LDAP_HOME_DIRECTORY, pd
+                            .getHomeDirectory());
                     addAttribute(attributes, LDAP_LOGIN_SHELL, pd.loginShell);
                 }
             }
-        
+
             AddRequest addRequest = new AddRequest(userDN, attributes);
             LDAPResult result = getConnection().add(addRequest);
             LdapDAO.checkLdapResult(result.getResultCode());
@@ -274,12 +286,14 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
             getConnection().reconnect();
             try
             {
-                 return getUser(user.getUserID(), config.getUserRequestsDN());
+                return getUser(user.getUserID(), config.getUserRequestsDN());
             }
             catch (UserNotFoundException e)
             {
-                throw new RuntimeException("BUG: new user " + userDN.toNormalizedString() +
-                                           " not found, result " + result.getResultCode());
+                throw new RuntimeException("BUG: new user " + userDN
+                        .toNormalizedString() +
+                                           " not found, result " + result
+                                                   .getResultCode());
             }
         }
         catch (LDAPException e)
@@ -287,7 +301,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
             System.out.println("LDAPe: " + e);
             System.out.println("LDAPrc: " + e.getResultCode());
             logger.debug("addUser Exception: " + e, e);
-            LdapDAO.checkLdapResult(e.getResultCode());
+            LdapUserDAO.checkUserLDAPResult(e.getResultCode());
             throw new RuntimeException("Unexpected LDAP exception", e);
         }
     }
@@ -302,17 +316,17 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
      * @throws AccessControlException If the operation is not permitted.
      */
     public User<T> getUser(final T userID)
-        throws UserNotFoundException, TransientException, AccessControlException
+            throws UserNotFoundException, TransientException,
+                   AccessControlException
     {
         return getUser(userID, config.getUsersDN());
     }
 
 
-
     /**
      * Get the user specified by userID.
      *
-     * @param userID The userID.
+     * @param userID  The userID.
      * @param usersDN The LDAP tree to search.
      * @return User instance.
      * @throws UserNotFoundException  when the user is not found.
@@ -320,7 +334,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
      * @throws AccessControlException If the operation is not permitted.
      */
     private User<T> getUser(final T userID, final String usersDN)
-        throws UserNotFoundException, TransientException, AccessControlException
+            throws UserNotFoundException, TransientException,
+                   AccessControlException
     {
         String searchField = userLdapAttrib.get(userID.getClass());
         if (searchField == null)
@@ -329,16 +344,16 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
                     "Unsupported principal type " + userID.getClass());
         }
 
-        searchField = "(&(objectclass=inetorgperson)(" + 
+        searchField = "(&(objectclass=inetorgperson)(" +
                       searchField + "=" + userID.getName() + "))";
         logger.debug(searchField);
 
         SearchResultEntry searchResult = null;
         try
         {
-            SearchRequest searchRequest = 
+            SearchRequest searchRequest =
                     new SearchRequest(usersDN, SearchScope.SUB,
-                                     searchField, userAttribs);
+                                      searchField, userAttribs);
 
             if (isSecure(usersDN))
             {
@@ -362,7 +377,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
         }
         User<T> user = new User<T>(userID);
         user.getIdentities().add(new HttpPrincipal(searchResult
-                .getAttributeValue(userLdapAttrib.get(HttpPrincipal.class))));
+                                                           .getAttributeValue(userLdapAttrib
+                                                                                      .get(HttpPrincipal.class))));
 
         String fname = searchResult.getAttributeValue(LDAP_FIRST_NAME);
         String lname = searchResult.getAttributeValue(LDAP_LAST_NAME);
@@ -371,27 +387,30 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
         personaDetails.city = searchResult.getAttributeValue(LDAP_CITY);
         personaDetails.country = searchResult.getAttributeValue(LDAP_COUNTRY);
         personaDetails.email = searchResult.getAttributeValue(LDAP_EMAIL);
-        personaDetails.institute = searchResult.getAttributeValue(LDAP_INSTITUTE);
+        personaDetails.institute = searchResult
+                .getAttributeValue(LDAP_INSTITUTE);
         user.details.add(personaDetails);
-        
+
         Long uid = searchResult.getAttributeValueAsLong(LDAP_UID_NUMBER);
         Long gid = searchResult.getAttributeValueAsLong(LDAP_GID_NUMBER);
-        String homeDirectory = searchResult.getAttributeValue(LDAP_HOME_DIRECTORY);
+        String homeDirectory = searchResult
+                .getAttributeValue(LDAP_HOME_DIRECTORY);
         if (uid != null && gid != null && homeDirectory != null)
         {
             PosixDetails posixDetails = new PosixDetails(uid, gid, homeDirectory);
-            posixDetails.loginShell = searchResult.getAttributeValue(LDAP_LOGIN_SHELL);
+            posixDetails.loginShell = searchResult
+                    .getAttributeValue(LDAP_LOGIN_SHELL);
             user.details.add(posixDetails);
         }
-        
+
         return user;
     }
 
     /**
      * Obtain whether the given DN tree requires authentication.
      *
-     * @param usersDN           The usersDN to check.
-     * @return              True if requires authentication, False otherwise.
+     * @param usersDN The usersDN to check.
+     * @return True if requires authentication, False otherwise.
      */
     private boolean isSecure(final String usersDN)
     {
@@ -400,23 +419,23 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
 
     /**
      * Get all group names.
-     * 
+     *
      * @return A collection of strings
-     * 
      * @throws TransientException If an temporary, unexpected problem occurred.
      */
     public Collection<String> getUserNames()
-        throws TransientException
+            throws TransientException
     {
         try
         {
             Filter filter = Filter.createPresenceFilter(LDAP_COMMON_NAME);
-            String [] attributes = new String[] {LDAP_COMMON_NAME, LDAP_NSACCOUNTLOCK};
-            
-            SearchRequest searchRequest = 
-                    new SearchRequest(config.getGroupsDN(), 
+            String[] attributes = new String[]{LDAP_COMMON_NAME,
+                                               LDAP_NSACCOUNTLOCK};
+
+            SearchRequest searchRequest =
+                    new SearchRequest(config.getGroupsDN(),
                                       SearchScope.SUB, filter, attributes);
-    
+
             SearchResult searchResult = null;
             try
             {
@@ -430,7 +449,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
                     throw new IllegalStateException("Could not find groups root");
                 }
             }
-            
+
             LdapDAO.checkLdapResult(searchResult.getResultCode());
             List<String> groupNames = new ArrayList<String>();
             for (SearchResultEntry next : searchResult.getSearchEntries())
@@ -440,49 +459,47 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
                     groupNames.add(next.getAttributeValue(LDAP_COMMON_NAME));
                 }
             }
-            
+
             return groupNames;
         }
         catch (LDAPException e1)
         {
-        	logger.debug("getGroupNames Exception: " + e1, e1);
+            logger.debug("getGroupNames Exception: " + e1, e1);
             LdapDAO.checkLdapResult(e1.getResultCode());
-            throw new IllegalStateException("Unexpected exception: " + e1.getMatchedDN(), e1);
+            throw new IllegalStateException("Unexpected exception: " + e1
+                    .getMatchedDN(), e1);
         }
     }
-    
+
     /**
      * Updated the user specified by User.
      *
      * @param user
-     *
      * @return User instance.
-     * 
-     * @throws UserNotFoundException when the user is not found.
-     * @throws TransientException If an temporary, unexpected problem occurred.
+     * @throws UserNotFoundException  when the user is not found.
+     * @throws TransientException     If an temporary, unexpected problem occurred.
      * @throws AccessControlException If the operation is not permitted.
      */
     public User<T> modifyUser(User<T> user)
-        throws UserNotFoundException, TransientException, 
-               AccessControlException
+            throws UserNotFoundException, TransientException,
+                   AccessControlException
     {
         return null;
     }
-    
+
     /**
      * Delete the user specified by userID.
      *
      * @param userID The userID.
-     * 
-     * @throws UserNotFoundException when the user is not found.
-     * @throws TransientException If an temporary, unexpected problem occurred.
+     * @throws UserNotFoundException  when the user is not found.
+     * @throws TransientException     If an temporary, unexpected problem occurred.
      * @throws AccessControlException If the operation is not permitted.
      */
     public void deleteUser(final T userID)
-        throws UserNotFoundException, TransientException, 
-               AccessControlException
+            throws UserNotFoundException, TransientException,
+                   AccessControlException
     {
-        
+
     }
 
     /**
@@ -539,7 +556,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
 
             if (searchResult != null)
             {
-                String[] members = searchResult.getAttributeValues(LDAP_MEMBEROF);
+                String[] members = searchResult
+                        .getAttributeValues(LDAP_MEMBEROF);
                 if (members != null)
                 {
                     for (String member : members)
@@ -668,20 +686,21 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
                     "Unsupported principal type " + user.getUserID()
                             .getClass());
         }
-        
+
         // change the DN to be in the 'java' format
         if (user.getUserID() instanceof X500Principal)
         {
             X500Principal orderedPrincipal = AuthenticationUtil.getOrderedForm(
-                (X500Principal) user.getUserID());
-            searchField = "(" + searchField + "=" + orderedPrincipal.toString() + ")";
+                    (X500Principal) user.getUserID());
+            searchField = "(" + searchField + "=" + orderedPrincipal
+                    .toString() + ")";
         }
         else
         {
             searchField = "(" + searchField + "=" + user.getUserID().getName()
-                    + ")";
+                          + ")";
         }
-        
+
         logger.debug("Search field is: " + searchField);
 
         SearchResultEntry searchResult = null;
@@ -709,9 +728,9 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
         }
         return searchResult.getAttributeValueAsDN(LDAP_ENTRYDN);
     }
-    
+
     protected DN getUserDN(final String userID)
-        throws LDAPException, TransientException
+            throws LDAPException, TransientException
     {
         try
         {
@@ -719,18 +738,19 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
         }
         catch (LDAPException e)
         {
-        	logger.debug("getUserDN Exception: " + e, e);
+            logger.debug("getUserDN Exception: " + e, e);
             LdapDAO.checkLdapResult(e.getResultCode());
         }
         throw new IllegalArgumentException(userID + " not a valid user ID");
     }
 
     protected DN getUserRequestsDN(final String userID)
-        throws LDAPException, TransientException
+            throws LDAPException, TransientException
     {
         try
         {
-            return new DN(LDAP_UID + "=" + userID + "," + config.getUserRequestsDN());
+            return new DN(LDAP_UID + "=" + userID + "," + config
+                    .getUserRequestsDN());
         }
         catch (LDAPException e)
         {
@@ -739,7 +759,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
         }
         throw new IllegalArgumentException(userID + " not a valid user ID");
     }
-    
+
     void addAttribute(List<Attribute> attributes, final String name, final String value)
     {
         if (value != null && !value.isEmpty())
@@ -748,4 +768,25 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
         }
     }
 
+    /**
+     * Checks the Ldap result code, and if the result is not SUCCESS,
+     * throws an appropriate exception. This is the place to decide on
+     * mapping between ldap errors and exception types
+     *
+     * @param code The code returned from an LDAP request.
+     * @throws TransientException
+     * @throws UserAlreadyExistsException
+     */
+    protected static void checkUserLDAPResult(final ResultCode code)
+            throws TransientException, UserAlreadyExistsException
+    {
+        if (code == ResultCode.ENTRY_ALREADY_EXISTS)
+        {
+            throw new UserAlreadyExistsException("User already exists.");
+        }
+        else
+        {
+            LdapDAO.checkLdapResult(code);
+        }
+    }
 }
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java
index 24ed9de31d091be757c41c65f177f4eb033f53d1..ef57b6d4b7cb84e8387a0ae4771a991028901aba 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java
@@ -69,6 +69,7 @@
 package ca.nrc.cadc.ac.server.ldap;
 
 import ca.nrc.cadc.ac.User;
+import ca.nrc.cadc.ac.UserAlreadyExistsException;
 import ca.nrc.cadc.ac.UserNotFoundException;
 import ca.nrc.cadc.ac.UserRequest;
 import ca.nrc.cadc.ac.server.UserPersistence;
@@ -127,8 +128,10 @@ public class LdapUserPersistence<T extends Principal>
      * @throws TransientException If an temporary, unexpected problem occurred.
      * @throws AccessControlException If the operation is not permitted.
      */
+    @Override
     public User<T> addUser(UserRequest<T> user)
-        throws TransientException, AccessControlException
+        throws TransientException, AccessControlException,
+               UserAlreadyExistsException
     {
         LdapUserDAO<T> userDAO = null;
         try
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java
index 81d25f43c80b34d1917a919930cce9af6e61d655..e7c0cda3d1566bfb6c7b435833f579e429104420 100644
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java
@@ -70,11 +70,13 @@ package ca.nrc.cadc.ac.server.web.users;
 
 import java.io.InputStream;
 import ca.nrc.cadc.ac.User;
+import ca.nrc.cadc.ac.UserAlreadyExistsException;
 import ca.nrc.cadc.ac.UserRequest;
 import ca.nrc.cadc.ac.server.UserPersistence;
 import ca.nrc.cadc.ac.xml.UserRequestReader;
 import ca.nrc.cadc.ac.xml.UserWriter;
 
+import javax.servlet.http.HttpServletResponse;
 import java.security.Principal;
 
 public class CreateUserAction<T extends Principal> extends UsersAction
@@ -92,9 +94,18 @@ public class CreateUserAction<T extends Principal> extends UsersAction
     {
         UserPersistence<Principal> userPersistence = getUserPersistence();
         UserRequest<Principal> userRequest = readUserRequest(this.inputStream);
-        User<Principal> newUser = userPersistence.addUser(userRequest);
-        writeUser(newUser);
-        logUserInfo(newUser.getUserID().getName());
+        try
+        {
+            User<Principal> newUser = userPersistence.addUser(userRequest);
+            writeUser(newUser);
+            logUserInfo(newUser.getUserID().getName());
+        }
+        catch (UserAlreadyExistsException e)
+        {
+            response.setStatus(HttpServletResponse.SC_CONFLICT);
+            response.getWriter().write("User already exists");
+        }
+
         return null;
     }
 
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java
index 260bc47f56f7a10e53cbc30281fffaaf77cfb0a8..2a6ec56c8d14cba6c98dfca1985ef8f0a25c901e 100644
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java
@@ -75,6 +75,7 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import ca.nrc.cadc.ac.UserAlreadyExistsException;
 import ca.nrc.cadc.util.StringUtil;
 import org.apache.log4j.Logger;