microsoft/garnet · error · ACLUserAlreadyExistsException

{username}

Error message

{username}

What it means

Thrown by AccessControlList.AddUserHandle when a user with the same username already exists in the concurrent user dictionary (TryAdd returns false). The username (derived from userHandle.User.Name) is reported via ACLUserAlreadyExistsException. The ACL does not allow two distinct user handles for one name.

Source

Thrown at libs/server/ACL/AccessControlList.cs:87

        /// <returns>The default user of this access control list.</returns>
        public UserHandle GetDefaultUserHandle()
        {
            return _defaultUserHandle;
        }

        /// <summary>
        /// Adds the given <see cref="UserHandle"/> to the ACL.
        /// </summary>
        /// <param name="userHandle">User to add to the list.</param>
        /// <exception cref="ACLUserAlreadyExistsException">Thrown if a user with the given username already exists.</exception>
        public void AddUserHandle(UserHandle userHandle)
        {
            var username = userHandle?.User.Name;

            // If a user with the given name already exists in the ACL, the new user cannot be added
            if (!_userHandles.TryAdd(username, userHandle))
            {
                throw new ACLUserAlreadyExistsException(username);
            }
        }

        /// <summary>
        /// Deletes the <see cref="UserHandle"/> associated with the given username.
        /// </summary>
        /// <param name="username">Username of the user to delete.</param>
        /// <returns>true if successful, false if no matching user was found.</returns>
        /// <exception cref="ACLException">Thrown if the given user exists but cannot be deleted.</exception>
        public bool DeleteUserHandle(string username)
        {
            if (username == DefaultUserName)
            {
                throw new ACLException("The special 'default' user cannot be removed from the system");
            }
            return _userHandles.TryRemove(username, out _);
        }

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Check GetUserHandle(username) == null before adding, or use a get-or-create pattern.
  2. De-duplicate ACL file definitions — each username should appear on a single aggregated line.
  3. Catch ACLUserAlreadyExistsException and fall back to retrieving the existing handle (as CreateDefaultUserHandle does).
  4. Do not re-add the 'default' user explicitly; it is auto-created.

Example fix

// before
acl.AddUserHandle(new UserHandle(new User("alice")));

// after
if (acl.GetUserHandle("alice") == null)
    acl.AddUserHandle(new UserHandle(new User("alice")));
Defensive patterns

Strategy: validation

Validate before calling

if (acl.GetUserHandle(username) != null)
    throw new InvalidOperationException($"User '{username}' already exists.");

Type guard

static bool UserAbsent(AccessControlList acl, string name) => acl.GetUserHandle(name) == null;

Try / catch

try { acl.AddUserHandle(handle); }
catch (ACLUserAlreadyExistsException) { handle = acl.GetUserHandle(name); }

Prevention

When it happens

Trigger: Calling AddUserHandle twice with handles whose User.Name collides; or adding a user while another thread/path already created it (the CreateDefaultUserHandle loop specifically catches this exception and retries the lookup instead).

Common situations: Loading an ACL file that defines the same username twice on different lines; programmatic user creation racing with file import; trying to re-add the 'default' user that always exists.

Related errors


AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13). Data as JSON: /api/errors/ce8122c650065ca1. Report an issue: GitHub.