flipped-aurora/gin-vue-admin · error
用户名已注册
Error message
用户名已注册
What it means
Register in UserService throws "用户名已注册" when a First() query on username does NOT return gorm.ErrRecordNotFound, i.e. a user with that username already exists. It prevents duplicate accounts before hashing the password and creating the record.
Source
Thrown at server/service/system/sys_user.go:33
"github.com/flipped-aurora/gin-vue-admin/server/utils/logger"
"github.com/google/uuid"
"gorm.io/gorm"
)
//@author: [piexlmax](https://github.com/piexlmax)
//@function: Register
//@description: 用户注册
//@param: u model.SysUser
//@return: userInter system.SysUser, err error
type UserService struct{}
var UserServiceApp = new(UserService)
func (userService *UserService) Register(ctx context.Context, u system.SysUser) (userInter system.SysUser, err error) {
var user system.SysUser
if !errors.Is(global.GVA_DB.WithContext(ctx).Where("username = ?", u.Username).First(&user).Error, gorm.ErrRecordNotFound) { // 判断用户名是否注册
return userInter, errors.New("用户名已注册")
}
// 否则 附加uuid 密码hash加密 注册
cfg := (&SecurityConfigService{}).Current(ctx)
u.MustChangePassword = cfg.ForceNewUserChangePassword
u.Password = utils.BcryptHash(u.Password)
u.UUID = uuid.New()
now := time.Now()
u.PasswordUpdatedAt = &now
err = global.GVA_DB.WithContext(ctx).Create(&u).Error
return u, err
}
//@author: [piexlmax](https://github.com/piexlmax)
//@author: [SliverHorn](https://github.com/SliverHorn)
//@function: Login
//@description: 用户登录
//@param: u *model.SysUser
//@return: err error, userInter *model.SysUserView on GitHub (pinned to 3136500ef3)
Solutions
- Choose a different username or instruct the user to log in instead of registering.
- Check the user table (including soft-deleted rows) for the conflicting name and clean up if appropriate.
- Trim/normalize the username client-side before submitting.
- Add a unique constraint on username as a backstop against registration races.
Example fix
// before
u.Username = rawForm.Username // " alice " vs existing "alice"
// after
u.Username = strings.TrimSpace(rawForm.Username)
if err := svc.Register(ctx, u); err != nil && strings.Contains(err.Error(), "用户名已注册") {
return fmt.Errorf("该用户名已被占用,请直接登录或更换用户名")
} Defensive patterns
Strategy: try-catch
Validate before calling
var existing system.SysUser
if err := db.Where("username = ?", username).First(&existing).Error; err == nil {
return errors.New("username already taken; choose another or log in")
} Try / catch
user, err := userService.Register(ctx, u)
if err != nil {
if strings.Contains(err.Error(), "用户名已注册") {
http.Error(w, "username already registered", http.StatusConflict)
return
}
http.Error(w, err.Error(), http.StatusInternalServerError)
} Prevention
- Check username availability in the UI before submission
- Disable the submit button after the first click to prevent double posts
- Trim and normalize usernames at registration
- Add a DB unique constraint on username as a race backstop
When it happens
Trigger: Calling the register API with a username already present in sys_user; double-submitting a registration form; a soft-deleted user row still matching the unique username (if not excluded by GORM soft-delete).
Common situations: Users re-registering with an existing name; concurrent race where two requests pass the check nearly simultaneously; test fixtures leaving a user with the same name in the DB; username case/whitespace differences not normalized.
Related errors
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/e72e2ef196b20786.
Report an issue: GitHub.