qiurunze123/miaosha · warning · RuntimeException

用户名已经存在!

Error message

用户名已经存在!

What it means

Thrown by LogininfoServiceImpl.register() when the supplied username already exists in the logininfo table. The method queries loginInfoMapper.getCountByNickname(username, USERTYPE_NORMAL) and, if count > 0, raises a raw RuntimeException with the literal message '用户名已经存在!' (Username already exists). Unlike the rest of the codebase, this uses java.lang.RuntimeException directly instead of the project's GlobleException, so the GlobalExceptionHandler will not map it to a structured ResultStatus code — it falls through to a generic 500.

Source

Thrown at miaosha-admin/miaosha-admin-service/src/main/java/com/geekq/admin/service/impl/LogininfoServiceImpl.java:75

            //MD5(MD5(password)+salt)
            logininfo.setPassword(MD5Utils.formPassToDBPass(password, salt));
            logininfo.setState(Constants.STATE_NORMAL);
            logininfo.setUserType(Constants.USERTYPE_NORMAL);
            logininfo.setRegisterDate(new Date());
            logininfo.setLastLoginDate(new Date());
            logininfo.setSalt(salt);
            this.loginInfoMapper.insert(logininfo);

            //初始化一个account
            Account account = Account.empty(logininfo.getId());
            accountMapper.insert(account);


            //初始化一个Userinfo
            Userinfo userinfo = Userinfo.empty(logininfo.getId());
            int result = this.userinfoMapper.insert(userinfo);
        } else {
            throw new RuntimeException("用户名已经存在!");
        }
    }

    @Override
    public boolean checkUsername(String name, int userType) {
        return this.loginInfoMapper.getCountByNickname(name, userType) <= 0;
    }

    @Override
    public ResultGeekQ<Logininfo> login(String name, String password, int userType, String ip) {
        ResultGeekQ<Logininfo> resultGeekQ = ResultGeekQ.build();

        try {
            IpLog log = new IpLog(name, new Date(), ip, userType, null);
            Logininfo logininfo = loginInfoMapper.getLoginInfoByNickname(name, Constants.USERTYPE_NORMAL);
            String salt = logininfo.getSalt();
            Logininfo current = this.loginInfoMapper.login(name,
                    MD5Utils.formPassToDBPass(password, salt), userType);

View on GitHub (pinned to e58017658e)

Solutions

  1. Call checkUsername(name, userType) before invoking register(); it returns true when the nickname is free (count <= 0).
  2. Add a unique database index on (nickname, userType) in the logininfo table so duplicates are rejected at the DB level even under concurrency.
  3. Replace the raw RuntimeException with GlobleException(RESIGETER_NICKNAMEEXIST) so the error is caught by GlobalExceptionHandler and returned as a structured code 200003 instead of an HTTP 500.
  4. Return a ResultGeekQ error from register() instead of throwing, matching the pattern used by login().

Example fix

// before
} else {
    throw new RuntimeException("用户名已经存在!");
}

// after
} else {
    throw new GlobleException(ResultStatus.RESIGETER_NICKNAMEEXIST);
}
Defensive patterns

Strategy: validation

Validate before calling

// Check before calling register()
boolean isAvailable = logininfoService.checkUsername(username, Constants.USERTYPE_NORMAL);
if (!isAvailable) {
    return ResultGeekQ.error(ResultStatus.RESIGETER_NICKNAMEEXIST);
}
logininfoService.register(username, password);

Try / catch

// Catch raw RuntimeException since register() does not use GlobleException
try {
    logininfoService.register(username, password);
} catch (RuntimeException e) {
    if (e.getMessage().contains("用户名已经存在")) {
        return ResultGeekQ.error(ResultStatus.RESIGETER_NICKNAMEEXIST);
    }
    throw e;
}

Prevention

When it happens

Trigger: POST to the admin register endpoint with a nickname that already has a row in logininfo where userType = USERTYPE_NORMAL. Two concurrent register calls with the same nickname can also trigger it because there is no DB unique constraint enforced in the insert path shown. Calling register() a second time with the same value always reproduces it.

Common situations: Registering a duplicate user during integration tests without cleaning the table; missing unique-constraint on the nickname column so a race condition lets two inserts through; front-end failing to call checkUsername() before submit; automated load tests reusing the same account name.

Related errors


AI-assisted analysis of qiurunze123/miaosha@e58017658e (2026-08-14). Data as JSON: /api/errors/1b257c93e7139482. Report an issue: GitHub.