{"record":{"id":"3e75a70b0b456f7f","repo":"TechnitiumSoftware/DnsServer","slug":"user-already-exists-newusername","errorCode":null,"errorMessage":"User already exists: {newUsername}","messagePattern":"User already exists: (.+?)","errorType":"exception","errorClass":"DnsWebServiceException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Auth/AuthManager.cs","lineNumber":986,"sourceCode":"        public bool HasDefaultCredentials()\n        {\n            User user = GetUser(\"admin\");\n\n            return (user is not null) && user.PasswordHash.Equals(user.GetPasswordHashFor(\"admin\"), StringComparison.Ordinal);\n        }\n\n        public void ChangeUsername(User user, string newUsername)\n        {\n            if (user.Username.Equals(newUsername, StringComparison.OrdinalIgnoreCase))\n                return;\n\n            string oldUsername = user.Username;\n            user.SetUsername(newUsername);\n\n            if (!_users.TryAdd(user.Username, user))\n            {\n                user.SetUsername(oldUsername); //revert\n                throw new DnsWebServiceException(\"User already exists: \" + newUsername);\n            }\n\n            _users.TryRemove(oldUsername, out _);\n        }\n\n        public async Task<User> ChangePasswordAsync(string username, string password, string totp, IPAddress remoteAddress, string newPassword, int iterations)\n        {\n            User user = await AuthenticateUserAsync(username, password, totp, remoteAddress);\n\n            user.ChangePassword(newPassword, iterations);\n\n            return user;\n        }\n\n        public bool DeleteUser(string username)\n        {\n            if (_users.TryRemove(username.ToLowerInvariant(), out User deletedUser))\n            {","sourceCodeStart":968,"sourceCodeEnd":1004,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Auth/AuthManager.cs#L968-L1004","documentation":"Thrown as DnsWebServiceException from ChangeUsername when TryAdd of the new username fails because that name is already taken. The username is reverted to the old value before throwing, leaving state consistent. Returned over the API as HTTP 200 with status 'error'.","triggerScenarios":"POST /api/users/changeUsername (or equivalent) targeting a newUsername that already exists as a (lowercased) key; a no-op fast path exists only if the new name equals the current name case-insensitively.","commonSituations":"Renaming a user to a name that collides with another active or local user; case-only target that differs from current only by case still triggers the collision because keys are lowercased and equality is OrdinalIgnoreCase on the fast path.","solutions":["Choose a username that does not exist (check case-insensitively).","Delete or rename the conflicting user first.","Verify the target name via GetUser before attempting the rename."],"exampleFix":"// before\n_authManager.ChangeUsername(user, newUsername);\n// after\nif (GetUser(newUsername) is null)\n    _authManager.ChangeUsername(user, newUsername);","handlingStrategy":"validation","validationCode":"if (await GetUserAsync(newUsername) is not null)\n    throw new InvalidOperationException($\"Username '{newUsername}' is taken.\");","typeGuard":null,"tryCatchPattern":"try { await client.ChangeUsernameAsync(user, newUsername); }\ncatch (HttpApiClientException ex) when (ex.Message.StartsWith(\"User already exists\"))\n{\n    PromptForDifferentUsername();\n}","preventionTips":["Check the target username case-insensitively before renaming.","Delete or rename conflicting users first."],"tags":["auth","user-management","duplicate"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}